fix mempool fix, to allow adding transactions out of order.

This commit is contained in:
blackjok3r
2018-12-20 19:56:00 +08:00
parent 261dfbcead
commit f128d49d2f
2 changed files with 25 additions and 26 deletions

View File

@@ -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<size_t>::max() >= std::numeric_limits<int64_t>::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<uint256> vWorkQueue;
vector<uint256> vEraseQueue;
CTransaction tx;