fix mempool fix, to allow adding transactions out of order.
This commit is contained in:
47
src/main.cpp
47
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<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;
|
||||
|
||||
Reference in New Issue
Block a user