mirror of
https://github.com/dashpay/dash.git
synced 2024-12-28 13:32:47 +01:00
commit
16eec89042
38
src/main.cpp
38
src/main.cpp
@ -691,13 +691,21 @@ bool CTxMemPool::accept(CTransaction &tx, bool fCheckInputs,
|
|||||||
|
|
||||||
if (fCheckInputs)
|
if (fCheckInputs)
|
||||||
{
|
{
|
||||||
CCoinsViewCache &view = *pcoinsTip;
|
CCoinsView dummy;
|
||||||
|
CCoinsViewCache view(dummy);
|
||||||
|
|
||||||
|
{
|
||||||
|
LOCK(cs);
|
||||||
|
CCoinsViewMemPool viewMemPool(*pcoinsTip, *this);
|
||||||
|
view.SetBackend(viewMemPool);
|
||||||
|
|
||||||
// do we already have it?
|
// do we already have it?
|
||||||
if (view.HaveCoins(hash))
|
if (view.HaveCoins(hash))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// 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),
|
||||||
|
// only helps filling in pfMissingInputs (to determine missing vs spent).
|
||||||
BOOST_FOREACH(const CTxIn txin, tx.vin) {
|
BOOST_FOREACH(const CTxIn txin, tx.vin) {
|
||||||
if (!view.HaveCoins(txin.prevout.hash)) {
|
if (!view.HaveCoins(txin.prevout.hash)) {
|
||||||
if (pfMissingInputs)
|
if (pfMissingInputs)
|
||||||
@ -706,8 +714,16 @@ bool CTxMemPool::accept(CTransaction &tx, bool fCheckInputs,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// are the actual inputs available?
|
||||||
if (!tx.HaveInputs(view))
|
if (!tx.HaveInputs(view))
|
||||||
return error("CTxMemPool::accept() : inputs already spent");
|
return error("CTxMemPool::accept() : inputs already spent");
|
||||||
|
|
||||||
|
// Bring the best block into scope
|
||||||
|
view.GetBestBlock();
|
||||||
|
|
||||||
|
// we have all inputs cached now, so switch back to dummy, so we don't need to keep lock on mempool
|
||||||
|
view.SetBackend(dummy);
|
||||||
|
}
|
||||||
|
|
||||||
// Check for non-standard pay-to-script-hash in inputs
|
// Check for non-standard pay-to-script-hash in inputs
|
||||||
if (!tx.AreInputsStandard(view) && !fTestNet)
|
if (!tx.AreInputsStandard(view) && !fTestNet)
|
||||||
@ -738,7 +754,6 @@ bool CTxMemPool::accept(CTransaction &tx, bool fCheckInputs,
|
|||||||
int64 nNow = GetTime();
|
int64 nNow = GetTime();
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs);
|
|
||||||
// Use an exponentially decaying ~10-minute window:
|
// Use an exponentially decaying ~10-minute window:
|
||||||
dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
|
dFreeCount *= pow(1.0 - 1.0/600.0, (double)(nNow - nLastTime));
|
||||||
nLastTime = nNow;
|
nLastTime = nNow;
|
||||||
@ -1319,7 +1334,9 @@ bool CTransaction::CheckInputs(CCoinsViewCache &inputs, enum CheckSig_mode csmod
|
|||||||
if (!HaveInputs(inputs))
|
if (!HaveInputs(inputs))
|
||||||
return error("CheckInputs() : %s inputs unavailable", GetHash().ToString().substr(0,10).c_str());
|
return error("CheckInputs() : %s inputs unavailable", GetHash().ToString().substr(0,10).c_str());
|
||||||
|
|
||||||
CBlockIndex *pindexBlock = inputs.GetBestBlock();
|
// While checking, GetBestBlock() refers to the parent block.
|
||||||
|
// This is also true for mempool checks.
|
||||||
|
int nSpendHeight = inputs.GetBestBlock()->nHeight + 1;
|
||||||
int64 nValueIn = 0;
|
int64 nValueIn = 0;
|
||||||
int64 nFees = 0;
|
int64 nFees = 0;
|
||||||
for (unsigned int i = 0; i < vin.size(); i++)
|
for (unsigned int i = 0; i < vin.size(); i++)
|
||||||
@ -1329,8 +1346,8 @@ bool CTransaction::CheckInputs(CCoinsViewCache &inputs, enum CheckSig_mode csmod
|
|||||||
|
|
||||||
// If prev is coinbase, check that it's matured
|
// If prev is coinbase, check that it's matured
|
||||||
if (coins.IsCoinBase()) {
|
if (coins.IsCoinBase()) {
|
||||||
if (pindexBlock->nHeight - coins.nHeight < COINBASE_MATURITY)
|
if (nSpendHeight - coins.nHeight < COINBASE_MATURITY)
|
||||||
return error("CheckInputs() : tried to spend coinbase at depth %d", pindexBlock->nHeight - coins.nHeight);
|
return error("CheckInputs() : tried to spend coinbase at depth %d", nSpendHeight - coins.nHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for negative or overflow input values
|
// Check for negative or overflow input values
|
||||||
@ -1595,6 +1612,9 @@ bool CBlock::ConnectBlock(CBlockIndex* pindex, CCoinsViewCache &view, bool fJust
|
|||||||
blockundo.vtxundo.push_back(txundo);
|
blockundo.vtxundo.push_back(txundo);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (vtx[0].GetValueOut() > GetBlockValue(pindex->nHeight, nFees))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (fJustCheck)
|
if (fJustCheck)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@ -1951,9 +1971,13 @@ bool CBlock::CheckBlock(bool fCheckPOW, bool fCheckMerkleRoot) const
|
|||||||
if (!tx.CheckTransaction())
|
if (!tx.CheckTransaction())
|
||||||
return DoS(tx.nDoS, error("CheckBlock() : CheckTransaction failed"));
|
return DoS(tx.nDoS, error("CheckBlock() : CheckTransaction failed"));
|
||||||
|
|
||||||
|
// Build the merkle tree already. We need it anyway later, and it makes the
|
||||||
|
// block cache the transaction hashes, which means they don't need to be
|
||||||
|
// recalculated many times during this block's validation.
|
||||||
|
BuildMerkleTree();
|
||||||
|
|
||||||
// Check for duplicate txids. This is caught by ConnectInputs(),
|
// Check for duplicate txids. This is caught by ConnectInputs(),
|
||||||
// but catching it earlier avoids a potential DoS attack:
|
// but catching it earlier avoids a potential DoS attack:
|
||||||
BuildMerkleTree();
|
|
||||||
set<uint256> uniqueTx;
|
set<uint256> uniqueTx;
|
||||||
for (unsigned int i=0; i<vtx.size(); i++) {
|
for (unsigned int i=0; i<vtx.size(); i++) {
|
||||||
uniqueTx.insert(GetTxHash(i));
|
uniqueTx.insert(GetTxHash(i));
|
||||||
@ -3825,7 +3849,7 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
|
|||||||
int64 nValueIn = coins.vout[txin.prevout.n].nValue;
|
int64 nValueIn = coins.vout[txin.prevout.n].nValue;
|
||||||
nTotalIn += nValueIn;
|
nTotalIn += nValueIn;
|
||||||
|
|
||||||
int nConf = pindexPrev->nHeight - coins.nHeight;
|
int nConf = pindexPrev->nHeight - coins.nHeight + 1;
|
||||||
|
|
||||||
dPriority += (double)nValueIn * nConf;
|
dPriority += (double)nValueIn * nConf;
|
||||||
}
|
}
|
||||||
|
17
src/main.h
17
src/main.h
@ -1820,7 +1820,11 @@ public:
|
|||||||
|
|
||||||
// Modify the currently active block index
|
// Modify the currently active block index
|
||||||
virtual bool SetBestBlock(CBlockIndex *pindex);
|
virtual bool SetBestBlock(CBlockIndex *pindex);
|
||||||
|
|
||||||
|
// Do a bulk modification (multiple SetCoins + one SetBestBlock)
|
||||||
virtual bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
|
virtual bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
|
||||||
|
|
||||||
|
// Calculate statistics about the unspent transaction output set
|
||||||
virtual bool GetStats(CCoinsStats &stats);
|
virtual bool GetStats(CCoinsStats &stats);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1851,14 +1855,25 @@ protected:
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
CCoinsViewCache(CCoinsView &baseIn, bool fDummy = false);
|
CCoinsViewCache(CCoinsView &baseIn, bool fDummy = false);
|
||||||
|
|
||||||
|
// Standard CCoinsView methods
|
||||||
bool GetCoins(uint256 txid, CCoins &coins);
|
bool GetCoins(uint256 txid, CCoins &coins);
|
||||||
bool SetCoins(uint256 txid, const CCoins &coins);
|
bool SetCoins(uint256 txid, const CCoins &coins);
|
||||||
bool HaveCoins(uint256 txid);
|
bool HaveCoins(uint256 txid);
|
||||||
CCoins &GetCoins(uint256 txid);
|
|
||||||
CBlockIndex *GetBestBlock();
|
CBlockIndex *GetBestBlock();
|
||||||
bool SetBestBlock(CBlockIndex *pindex);
|
bool SetBestBlock(CBlockIndex *pindex);
|
||||||
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
|
bool BatchWrite(const std::map<uint256, CCoins> &mapCoins, CBlockIndex *pindex);
|
||||||
|
|
||||||
|
// Return a modifiable reference to a CCoins. Check HaveCoins first.
|
||||||
|
// Many methods explicitly require a CCoinsViewCache because of this method, to reduce
|
||||||
|
// copying.
|
||||||
|
CCoins &GetCoins(uint256 txid);
|
||||||
|
|
||||||
|
// Push the modifications applied to this cache to its base.
|
||||||
|
// Failure to call this method before destruction will cause the changes to be forgotten.
|
||||||
bool Flush();
|
bool Flush();
|
||||||
|
|
||||||
|
// Calculate the size of the cache (in number of transactions)
|
||||||
unsigned int GetCacheSize();
|
unsigned int GetCacheSize();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
Loading…
Reference in New Issue
Block a user