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 )
|
if ( nextBlockHeight <= 1 || chainActive.LastTip() == 0 )
|
||||||
tiptime = (uint32_t)time(NULL);
|
tiptime = (uint32_t)time(NULL);
|
||||||
else tiptime = (uint32_t)chainActive.LastTip()->nTime;
|
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
|
// 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");
|
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);
|
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)
|
// Rather not work on nonstandard transactions (unless -testnet/-regtest)
|
||||||
string reason;
|
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());
|
//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
|
// 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
|
// block; we don't want our mempool filled up with transactions that can't
|
||||||
// be mined yet.
|
// 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");
|
//fprintf(stderr,"AcceptToMemoryPool reject non-final\n");
|
||||||
return state.DoS(0, false, REJECT_NONSTANDARD, "non-final");
|
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
|
// Check for conflicts with in-memory transactions
|
||||||
|
if (!fSkipExpiry)
|
||||||
{
|
{
|
||||||
LOCK(pool.cs); // protect pool.mapNextTx
|
LOCK(pool.cs); // protect pool.mapNextTx
|
||||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
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))
|
if (ExistsImportTombstone(tx, view))
|
||||||
return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists");
|
return state.Invalid(false, REJECT_DUPLICATE, "import tombstone exists");
|
||||||
}
|
}
|
||||||
else
|
else if (!fSkipExpiry)
|
||||||
{
|
{
|
||||||
// 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),
|
||||||
@@ -1768,10 +1770,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||||||
if (pfMissingInputs)
|
if (pfMissingInputs)
|
||||||
*pfMissingInputs = true;
|
*pfMissingInputs = true;
|
||||||
//fprintf(stderr,"missing inputs\n");
|
//fprintf(stderr,"missing inputs\n");
|
||||||
if (!fSkipExpiry)
|
return state.DoS(0, error("AcceptToMemoryPool: tx inputs not found"),REJECT_INVALID, "bad-txns-inputs-missing");
|
||||||
return state.DoS(0, error("AcceptToMemoryPool: tx inputs not found"),REJECT_INVALID, "bad-txns-inputs-missing");
|
|
||||||
else
|
|
||||||
return(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1779,10 +1778,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||||||
if (!view.HaveInputs(tx))
|
if (!view.HaveInputs(tx))
|
||||||
{
|
{
|
||||||
//fprintf(stderr,"accept failure.1\n");
|
//fprintf(stderr,"accept failure.1\n");
|
||||||
if (!fSkipExpiry)
|
return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent");
|
||||||
return state.Invalid(error("AcceptToMemoryPool: inputs already spent"),REJECT_DUPLICATE, "bad-txns-inputs-spent");
|
|
||||||
else
|
|
||||||
return(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// are the joinsplit's requirements met?
|
// 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
|
// Keep track of transactions that spend a coinbase, which we re-scan
|
||||||
// during reorgs to ensure COINBASE_MATURITY is still met.
|
// during reorgs to ensure COINBASE_MATURITY is still met.
|
||||||
bool fSpendsCoinbase = false;
|
bool fSpendsCoinbase = false;
|
||||||
if (!tx.IsCoinImport()) {
|
if (!fSkipExpiry && !tx.IsCoinImport()) {
|
||||||
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
|
BOOST_FOREACH(const CTxIn &txin, tx.vin) {
|
||||||
const CCoins *coins = view.AccessCoins(txin.prevout.hash);
|
const CCoins *coins = view.AccessCoins(txin.prevout.hash);
|
||||||
if (coins->IsCoinBase()) {
|
if (coins->IsCoinBase()) {
|
||||||
@@ -1901,7 +1897,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||||||
// Check against previous transactions
|
// Check against previous transactions
|
||||||
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
// This is done last to help prevent CPU exhaustion denial-of-service attacks.
|
||||||
PrecomputedTransactionData txdata(tx);
|
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");
|
//fprintf(stderr,"accept failure.9\n");
|
||||||
return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString());
|
return error("AcceptToMemoryPool: ConnectInputs failed %s", hash.ToString());
|
||||||
@@ -1922,7 +1918,7 @@ bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransa
|
|||||||
flag = 1;
|
flag = 1;
|
||||||
KOMODO_CONNECTING = (1<<30) + (int32_t)chainActive.LastTip()->GetHeight() + 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 )
|
if ( flag != 0 )
|
||||||
KOMODO_CONNECTING = -1;
|
KOMODO_CONNECTING = -1;
|
||||||
@@ -4719,6 +4715,9 @@ bool CheckBlock(int32_t *futureblockp,int32_t height,CBlockIndex *pindex,const C
|
|||||||
// Check transactions
|
// Check transactions
|
||||||
CTransaction sTx;
|
CTransaction sTx;
|
||||||
CTransaction *ptx = NULL;
|
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
|
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;
|
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))
|
if (!CheckTransaction(tiptime,tx, state, verifier))
|
||||||
return error("CheckBlock: CheckTransaction failed");
|
return error("CheckBlock: CheckTransaction failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int nSigOps = 0;
|
unsigned int nSigOps = 0;
|
||||||
BOOST_FOREACH(const CTransaction& tx, block.vtx)
|
BOOST_FOREACH(const CTransaction& tx, block.vtx)
|
||||||
{
|
{
|
||||||
@@ -7018,6 +7018,9 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
|||||||
|
|
||||||
else if (strCommand == "tx")
|
else if (strCommand == "tx")
|
||||||
{
|
{
|
||||||
|
if (IsInitialBlockDownload())
|
||||||
|
return true;
|
||||||
|
|
||||||
vector<uint256> vWorkQueue;
|
vector<uint256> vWorkQueue;
|
||||||
vector<uint256> vEraseQueue;
|
vector<uint256> vEraseQueue;
|
||||||
CTransaction tx;
|
CTransaction tx;
|
||||||
|
|||||||
@@ -639,10 +639,6 @@ UniValue getlastsegidstakes(const UniValue& params, bool fHelp)
|
|||||||
for (int64_t i = chainActive.Height(); i > chainActive.Height()-depth; i--)
|
for (int64_t i = chainActive.Height(); i > chainActive.Height()-depth; i--)
|
||||||
{
|
{
|
||||||
CBlockIndex* pblockindex = chainActive[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 )
|
if ( pblockindex->segid >= 0 )
|
||||||
segids[pblockindex->segid] += 1;
|
segids[pblockindex->segid] += 1;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user