Merge remote-tracking branch 'jgarzik/mempool'
This commit is contained in:
commit
c23617fef3
3 changed files with 105 additions and 77 deletions
|
@ -367,7 +367,7 @@ Value getmininginfo(const Array& params, bool fHelp)
|
||||||
obj.push_back(Pair("generate", GetBoolArg("-gen")));
|
obj.push_back(Pair("generate", GetBoolArg("-gen")));
|
||||||
obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
|
obj.push_back(Pair("genproclimit", (int)GetArg("-genproclimit", -1)));
|
||||||
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
|
obj.push_back(Pair("hashespersec", gethashespersec(params, false)));
|
||||||
obj.push_back(Pair("pooledtx", (uint64_t)nPooledTx));
|
obj.push_back(Pair("pooledtx", (uint64_t)mempool.size()));
|
||||||
obj.push_back(Pair("testnet", fTestNet));
|
obj.push_back(Pair("testnet", fTestNet));
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
145
src/main.cpp
145
src/main.cpp
|
@ -23,10 +23,8 @@ set<CWallet*> setpwalletRegistered;
|
||||||
|
|
||||||
CCriticalSection cs_main;
|
CCriticalSection cs_main;
|
||||||
|
|
||||||
static map<uint256, CTransaction> mapTransactions;
|
CTxMemPool mempool;
|
||||||
CCriticalSection cs_mapTransactions;
|
|
||||||
unsigned int nTransactionsUpdated = 0;
|
unsigned int nTransactionsUpdated = 0;
|
||||||
map<COutPoint, CInPoint> mapNextTx;
|
|
||||||
|
|
||||||
map<uint256, CBlockIndex*> mapBlockIndex;
|
map<uint256, CBlockIndex*> mapBlockIndex;
|
||||||
uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
|
||||||
|
@ -451,31 +449,32 @@ bool CTransaction::CheckTransaction() const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs)
|
bool CTxMemPool::accept(CTxDB& txdb, CTransaction &tx, bool fCheckInputs,
|
||||||
|
bool* pfMissingInputs)
|
||||||
{
|
{
|
||||||
if (pfMissingInputs)
|
if (pfMissingInputs)
|
||||||
*pfMissingInputs = false;
|
*pfMissingInputs = false;
|
||||||
|
|
||||||
if (!CheckTransaction())
|
if (!tx.CheckTransaction())
|
||||||
return error("AcceptToMemoryPool() : CheckTransaction failed");
|
return error("CTxMemPool::accept() : CheckTransaction failed");
|
||||||
|
|
||||||
// Coinbase is only valid in a block, not as a loose transaction
|
// Coinbase is only valid in a block, not as a loose transaction
|
||||||
if (IsCoinBase())
|
if (tx.IsCoinBase())
|
||||||
return DoS(100, error("AcceptToMemoryPool() : coinbase as individual tx"));
|
return tx.DoS(100, error("CTxMemPool::accept() : coinbase as individual tx"));
|
||||||
|
|
||||||
// To help v0.1.5 clients who would see it as a negative number
|
// To help v0.1.5 clients who would see it as a negative number
|
||||||
if ((int64)nLockTime > std::numeric_limits<int>::max())
|
if ((int64)tx.nLockTime > std::numeric_limits<int>::max())
|
||||||
return error("AcceptToMemoryPool() : not accepting nLockTime beyond 2038 yet");
|
return error("CTxMemPool::accept() : not accepting nLockTime beyond 2038 yet");
|
||||||
|
|
||||||
// Rather not work on nonstandard transactions (unless -testnet)
|
// Rather not work on nonstandard transactions (unless -testnet)
|
||||||
if (!fTestNet && !IsStandard())
|
if (!fTestNet && !tx.IsStandard())
|
||||||
return error("AcceptToMemoryPool() : nonstandard transaction type");
|
return error("CTxMemPool::accept() : nonstandard transaction type");
|
||||||
|
|
||||||
// Do we already have it?
|
// Do we already have it?
|
||||||
uint256 hash = GetHash();
|
uint256 hash = tx.GetHash();
|
||||||
{
|
{
|
||||||
LOCK(cs_mapTransactions);
|
LOCK(cs);
|
||||||
if (mapTransactions.count(hash))
|
if (mapTx.count(hash))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (fCheckInputs)
|
if (fCheckInputs)
|
||||||
|
@ -484,9 +483,9 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
|
||||||
|
|
||||||
// Check for conflicts with in-memory transactions
|
// Check for conflicts with in-memory transactions
|
||||||
CTransaction* ptxOld = NULL;
|
CTransaction* ptxOld = NULL;
|
||||||
for (unsigned int i = 0; i < vin.size(); i++)
|
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||||
{
|
{
|
||||||
COutPoint outpoint = vin[i].prevout;
|
COutPoint outpoint = tx.vin[i].prevout;
|
||||||
if (mapNextTx.count(outpoint))
|
if (mapNextTx.count(outpoint))
|
||||||
{
|
{
|
||||||
// Disable replacement feature for now
|
// Disable replacement feature for now
|
||||||
|
@ -498,11 +497,11 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
|
||||||
ptxOld = mapNextTx[outpoint].ptx;
|
ptxOld = mapNextTx[outpoint].ptx;
|
||||||
if (ptxOld->IsFinal())
|
if (ptxOld->IsFinal())
|
||||||
return false;
|
return false;
|
||||||
if (!IsNewerThan(*ptxOld))
|
if (!tx.IsNewerThan(*ptxOld))
|
||||||
return false;
|
return false;
|
||||||
for (unsigned int i = 0; i < vin.size(); i++)
|
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||||
{
|
{
|
||||||
COutPoint outpoint = vin[i].prevout;
|
COutPoint outpoint = tx.vin[i].prevout;
|
||||||
if (!mapNextTx.count(outpoint) || mapNextTx[outpoint].ptx != ptxOld)
|
if (!mapNextTx.count(outpoint) || mapNextTx[outpoint].ptx != ptxOld)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -515,29 +514,29 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
|
||||||
MapPrevTx mapInputs;
|
MapPrevTx mapInputs;
|
||||||
map<uint256, CTxIndex> mapUnused;
|
map<uint256, CTxIndex> mapUnused;
|
||||||
bool fInvalid = false;
|
bool fInvalid = false;
|
||||||
if (!FetchInputs(txdb, mapUnused, false, false, mapInputs, fInvalid))
|
if (!tx.FetchInputs(txdb, mapUnused, false, false, mapInputs, fInvalid))
|
||||||
{
|
{
|
||||||
if (fInvalid)
|
if (fInvalid)
|
||||||
return error("AcceptToMemoryPool() : FetchInputs found invalid tx %s", hash.ToString().substr(0,10).c_str());
|
return error("CTxMemPool::accept() : FetchInputs found invalid tx %s", hash.ToString().substr(0,10).c_str());
|
||||||
if (pfMissingInputs)
|
if (pfMissingInputs)
|
||||||
*pfMissingInputs = true;
|
*pfMissingInputs = true;
|
||||||
return error("AcceptToMemoryPool() : FetchInputs failed %s", hash.ToString().substr(0,10).c_str());
|
return error("CTxMemPool::accept() : FetchInputs failed %s", hash.ToString().substr(0,10).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for non-standard pay-to-script-hash in inputs
|
// Check for non-standard pay-to-script-hash in inputs
|
||||||
if (!AreInputsStandard(mapInputs) && !fTestNet)
|
if (!tx.AreInputsStandard(mapInputs) && !fTestNet)
|
||||||
return error("AcceptToMemoryPool() : nonstandard transaction input");
|
return error("CTxMemPool::accept() : nonstandard transaction input");
|
||||||
|
|
||||||
// Note: if you modify this code to accept non-standard transactions, then
|
// Note: if you modify this code to accept non-standard transactions, then
|
||||||
// you should add code here to check that the transaction does a
|
// you should add code here to check that the transaction does a
|
||||||
// reasonable number of ECDSA signature verifications.
|
// reasonable number of ECDSA signature verifications.
|
||||||
|
|
||||||
int64 nFees = GetValueIn(mapInputs)-GetValueOut();
|
int64 nFees = tx.GetValueIn(mapInputs)-tx.GetValueOut();
|
||||||
unsigned int nSize = ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION);
|
unsigned int nSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
|
||||||
|
|
||||||
// Don't accept it if it can't get into a block
|
// Don't accept it if it can't get into a block
|
||||||
if (nFees < GetMinFee(1000, true, GMF_RELAY))
|
if (nFees < tx.GetMinFee(1000, true, GMF_RELAY))
|
||||||
return error("AcceptToMemoryPool() : not enough fees");
|
return error("CTxMemPool::accept() : not enough fees");
|
||||||
|
|
||||||
// Continuously rate-limit free transactions
|
// Continuously rate-limit free transactions
|
||||||
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
|
// This mitigates 'penny-flooding' -- sending thousands of free transactions just to
|
||||||
|
@ -556,8 +555,8 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
|
||||||
nLastTime = nNow;
|
nLastTime = nNow;
|
||||||
// -limitfreerelay unit is thousand-bytes-per-minute
|
// -limitfreerelay unit is thousand-bytes-per-minute
|
||||||
// At default rate it would take over a month to fill 1GB
|
// At default rate it would take over a month to fill 1GB
|
||||||
if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe(*this))
|
if (dFreeCount > GetArg("-limitfreerelay", 15)*10*1000 && !IsFromMe(tx))
|
||||||
return error("AcceptToMemoryPool() : free transaction rejected by rate limiter");
|
return error("CTxMemPool::accept() : free transaction rejected by rate limiter");
|
||||||
if (fDebug)
|
if (fDebug)
|
||||||
printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
|
printf("Rate limit dFreeCount: %g => %g\n", dFreeCount, dFreeCount+nSize);
|
||||||
dFreeCount += nSize;
|
dFreeCount += nSize;
|
||||||
|
@ -566,21 +565,21 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
|
||||||
|
|
||||||
// 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.
|
||||||
if (!ConnectInputs(mapInputs, mapUnused, CDiskTxPos(1,1,1), pindexBest, false, false))
|
if (!tx.ConnectInputs(mapInputs, mapUnused, CDiskTxPos(1,1,1), pindexBest, false, false))
|
||||||
{
|
{
|
||||||
return error("AcceptToMemoryPool() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str());
|
return error("CTxMemPool::accept() : ConnectInputs failed %s", hash.ToString().substr(0,10).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store transaction in memory
|
// Store transaction in memory
|
||||||
{
|
{
|
||||||
LOCK(cs_mapTransactions);
|
LOCK(cs);
|
||||||
if (ptxOld)
|
if (ptxOld)
|
||||||
{
|
{
|
||||||
printf("AcceptToMemoryPool() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
|
printf("CTxMemPool::accept() : replacing tx %s with new version\n", ptxOld->GetHash().ToString().c_str());
|
||||||
ptxOld->RemoveFromMemoryPool();
|
remove(*ptxOld);
|
||||||
}
|
}
|
||||||
AddToMemoryPoolUnchecked();
|
addUnchecked(tx);
|
||||||
}
|
}
|
||||||
|
|
||||||
///// are we sure this is ok when loading transactions or restoring block txes
|
///// are we sure this is ok when loading transactions or restoring block txes
|
||||||
|
@ -588,43 +587,44 @@ bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMi
|
||||||
if (ptxOld)
|
if (ptxOld)
|
||||||
EraseFromWallets(ptxOld->GetHash());
|
EraseFromWallets(ptxOld->GetHash());
|
||||||
|
|
||||||
printf("AcceptToMemoryPool(): accepted %s\n", hash.ToString().substr(0,10).c_str());
|
printf("CTxMemPool::accept() : accepted %s\n", hash.ToString().substr(0,10).c_str());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 nPooledTx = 0;
|
bool CTransaction::AcceptToMemoryPool(CTxDB& txdb, bool fCheckInputs, bool* pfMissingInputs)
|
||||||
|
|
||||||
bool CTransaction::AddToMemoryPoolUnchecked()
|
|
||||||
{
|
{
|
||||||
printf("AcceptToMemoryPoolUnchecked(): size %lu\n", mapTransactions.size());
|
return mempool.accept(txdb, *this, fCheckInputs, pfMissingInputs);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CTxMemPool::addUnchecked(CTransaction &tx)
|
||||||
|
{
|
||||||
|
printf("addUnchecked(): size %lu\n", mapTx.size());
|
||||||
// Add to memory pool without checking anything. Don't call this directly,
|
// Add to memory pool without checking anything. Don't call this directly,
|
||||||
// call AcceptToMemoryPool to properly check the transaction first.
|
// call CTxMemPool::accept to properly check the transaction first.
|
||||||
{
|
{
|
||||||
LOCK(cs_mapTransactions);
|
LOCK(cs);
|
||||||
uint256 hash = GetHash();
|
uint256 hash = tx.GetHash();
|
||||||
mapTransactions[hash] = *this;
|
mapTx[hash] = tx;
|
||||||
for (unsigned int i = 0; i < vin.size(); i++)
|
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||||
mapNextTx[vin[i].prevout] = CInPoint(&mapTransactions[hash], i);
|
mapNextTx[tx.vin[i].prevout] = CInPoint(&mapTx[hash], i);
|
||||||
nTransactionsUpdated++;
|
nTransactionsUpdated++;
|
||||||
++nPooledTx;
|
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CTransaction::RemoveFromMemoryPool()
|
bool CTxMemPool::remove(CTransaction &tx)
|
||||||
{
|
{
|
||||||
// Remove transaction from memory pool
|
// Remove transaction from memory pool
|
||||||
{
|
{
|
||||||
LOCK(cs_mapTransactions);
|
LOCK(cs);
|
||||||
uint256 hash = GetHash();
|
uint256 hash = tx.GetHash();
|
||||||
if (mapTransactions.count(hash))
|
if (mapTx.count(hash))
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(const CTxIn& txin, vin)
|
BOOST_FOREACH(const CTxIn& txin, tx.vin)
|
||||||
mapNextTx.erase(txin.prevout);
|
mapNextTx.erase(txin.prevout);
|
||||||
mapTransactions.erase(hash);
|
mapTx.erase(hash);
|
||||||
nTransactionsUpdated++;
|
nTransactionsUpdated++;
|
||||||
--nPooledTx;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -695,14 +695,14 @@ bool CWalletTx::AcceptWalletTransaction(CTxDB& txdb, bool fCheckInputs)
|
||||||
{
|
{
|
||||||
|
|
||||||
{
|
{
|
||||||
LOCK(cs_mapTransactions);
|
LOCK(mempool.cs);
|
||||||
// Add previous supporting transactions first
|
// Add previous supporting transactions first
|
||||||
BOOST_FOREACH(CMerkleTx& tx, vtxPrev)
|
BOOST_FOREACH(CMerkleTx& tx, vtxPrev)
|
||||||
{
|
{
|
||||||
if (!tx.IsCoinBase())
|
if (!tx.IsCoinBase())
|
||||||
{
|
{
|
||||||
uint256 hash = tx.GetHash();
|
uint256 hash = tx.GetHash();
|
||||||
if (!mapTransactions.count(hash) && !txdb.ContainsTx(hash))
|
if (!mempool.exists(hash) && !txdb.ContainsTx(hash))
|
||||||
tx.AcceptToMemoryPool(txdb, fCheckInputs);
|
tx.AcceptToMemoryPool(txdb, fCheckInputs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1017,10 +1017,10 @@ bool CTransaction::FetchInputs(CTxDB& txdb, const map<uint256, CTxIndex>& mapTes
|
||||||
{
|
{
|
||||||
// Get prev tx from single transactions in memory
|
// Get prev tx from single transactions in memory
|
||||||
{
|
{
|
||||||
LOCK(cs_mapTransactions);
|
LOCK(mempool.cs);
|
||||||
if (!mapTransactions.count(prevout.hash))
|
if (!mempool.exists(prevout.hash))
|
||||||
return error("FetchInputs() : %s mapTransactions prev not found %s", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str());
|
return error("FetchInputs() : %s mempool Tx prev not found %s", GetHash().ToString().substr(0,10).c_str(), prevout.hash.ToString().substr(0,10).c_str());
|
||||||
txPrev = mapTransactions[prevout.hash];
|
txPrev = mempool.lookup(prevout.hash);
|
||||||
}
|
}
|
||||||
if (!fFound)
|
if (!fFound)
|
||||||
txindex.vSpent.resize(txPrev.vout.size());
|
txindex.vSpent.resize(txPrev.vout.size());
|
||||||
|
@ -1183,15 +1183,15 @@ bool CTransaction::ClientConnectInputs()
|
||||||
|
|
||||||
// Take over previous transactions' spent pointers
|
// Take over previous transactions' spent pointers
|
||||||
{
|
{
|
||||||
LOCK(cs_mapTransactions);
|
LOCK(mempool.cs);
|
||||||
int64 nValueIn = 0;
|
int64 nValueIn = 0;
|
||||||
for (unsigned int i = 0; i < vin.size(); i++)
|
for (unsigned int i = 0; i < vin.size(); i++)
|
||||||
{
|
{
|
||||||
// Get prev tx from single transactions in memory
|
// Get prev tx from single transactions in memory
|
||||||
COutPoint prevout = vin[i].prevout;
|
COutPoint prevout = vin[i].prevout;
|
||||||
if (!mapTransactions.count(prevout.hash))
|
if (!mempool.exists(prevout.hash))
|
||||||
return false;
|
return false;
|
||||||
CTransaction& txPrev = mapTransactions[prevout.hash];
|
CTransaction& txPrev = mempool.lookup(prevout.hash);
|
||||||
|
|
||||||
if (prevout.n >= txPrev.vout.size())
|
if (prevout.n >= txPrev.vout.size())
|
||||||
return false;
|
return false;
|
||||||
|
@ -1200,7 +1200,8 @@ bool CTransaction::ClientConnectInputs()
|
||||||
if (!VerifySignature(txPrev, *this, i, true, 0))
|
if (!VerifySignature(txPrev, *this, i, true, 0))
|
||||||
return error("ConnectInputs() : VerifySignature failed");
|
return error("ConnectInputs() : VerifySignature failed");
|
||||||
|
|
||||||
///// this is redundant with the mapNextTx stuff, not sure which I want to get rid of
|
///// this is redundant with the mempool.mapNextTx stuff,
|
||||||
|
///// not sure which I want to get rid of
|
||||||
///// this has to go away now that posNext is gone
|
///// this has to go away now that posNext is gone
|
||||||
// // Check for conflicts
|
// // Check for conflicts
|
||||||
// if (!txPrev.vout[prevout.n].posNext.IsNull())
|
// if (!txPrev.vout[prevout.n].posNext.IsNull())
|
||||||
|
@ -1436,7 +1437,7 @@ bool static Reorganize(CTxDB& txdb, CBlockIndex* pindexNew)
|
||||||
|
|
||||||
// Delete redundant memory transactions that are in the connected branch
|
// Delete redundant memory transactions that are in the connected branch
|
||||||
BOOST_FOREACH(CTransaction& tx, vDelete)
|
BOOST_FOREACH(CTransaction& tx, vDelete)
|
||||||
tx.RemoveFromMemoryPool();
|
mempool.remove(tx);
|
||||||
|
|
||||||
printf("REORGANIZE: done\n");
|
printf("REORGANIZE: done\n");
|
||||||
|
|
||||||
|
@ -1472,7 +1473,7 @@ bool CBlock::SetBestChainInner(CTxDB& txdb, CBlockIndex *pindexNew)
|
||||||
|
|
||||||
// Delete redundant memory transactions
|
// Delete redundant memory transactions
|
||||||
BOOST_FOREACH(CTransaction& tx, vtx)
|
BOOST_FOREACH(CTransaction& tx, vtx)
|
||||||
tx.RemoveFromMemoryPool();
|
mempool.remove(tx);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2139,8 +2140,8 @@ bool static AlreadyHave(CTxDB& txdb, const CInv& inv)
|
||||||
{
|
{
|
||||||
bool txInMap = false;
|
bool txInMap = false;
|
||||||
{
|
{
|
||||||
LOCK(cs_mapTransactions);
|
LOCK(mempool.cs);
|
||||||
txInMap = (mapTransactions.count(inv.hash) != 0);
|
txInMap = (mempool.exists(inv.hash));
|
||||||
}
|
}
|
||||||
return txInMap ||
|
return txInMap ||
|
||||||
mapOrphanTransactions.count(inv.hash) ||
|
mapOrphanTransactions.count(inv.hash) ||
|
||||||
|
@ -3129,14 +3130,14 @@ CBlock* CreateNewBlock(CReserveKey& reservekey)
|
||||||
// Collect memory pool transactions into the block
|
// Collect memory pool transactions into the block
|
||||||
int64 nFees = 0;
|
int64 nFees = 0;
|
||||||
{
|
{
|
||||||
LOCK2(cs_main, cs_mapTransactions);
|
LOCK2(cs_main, mempool.cs);
|
||||||
CTxDB txdb("r");
|
CTxDB txdb("r");
|
||||||
|
|
||||||
// Priority order to process transactions
|
// Priority order to process transactions
|
||||||
list<COrphan> vOrphan; // list memory doesn't move
|
list<COrphan> vOrphan; // list memory doesn't move
|
||||||
map<uint256, vector<COrphan*> > mapDependers;
|
map<uint256, vector<COrphan*> > mapDependers;
|
||||||
multimap<double, CTransaction*> mapPriority;
|
multimap<double, CTransaction*> mapPriority;
|
||||||
for (map<uint256, CTransaction>::iterator mi = mapTransactions.begin(); mi != mapTransactions.end(); ++mi)
|
for (map<uint256, CTransaction>::iterator mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi)
|
||||||
{
|
{
|
||||||
CTransaction& tx = (*mi).second;
|
CTransaction& tx = (*mi).second;
|
||||||
if (tx.IsCoinBase() || !tx.IsFinal())
|
if (tx.IsCoinBase() || !tx.IsFinal())
|
||||||
|
|
35
src/main.h
35
src/main.h
|
@ -60,7 +60,6 @@ extern CBigNum bnBestChainWork;
|
||||||
extern CBigNum bnBestInvalidWork;
|
extern CBigNum bnBestInvalidWork;
|
||||||
extern uint256 hashBestChain;
|
extern uint256 hashBestChain;
|
||||||
extern CBlockIndex* pindexBest;
|
extern CBlockIndex* pindexBest;
|
||||||
extern uint64 nPooledTx;
|
|
||||||
extern unsigned int nTransactionsUpdated;
|
extern unsigned int nTransactionsUpdated;
|
||||||
extern uint64 nLastBlockTx;
|
extern uint64 nLastBlockTx;
|
||||||
extern uint64 nLastBlockSize;
|
extern uint64 nLastBlockSize;
|
||||||
|
@ -682,9 +681,6 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const CTxOut& GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const;
|
const CTxOut& GetOutputFor(const CTxIn& input, const MapPrevTx& inputs) const;
|
||||||
bool AddToMemoryPoolUnchecked();
|
|
||||||
public:
|
|
||||||
bool RemoveFromMemoryPool();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -1601,4 +1597,35 @@ public:
|
||||||
bool ProcessAlert();
|
bool ProcessAlert();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class CTxMemPool
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
mutable CCriticalSection cs;
|
||||||
|
std::map<uint256, CTransaction> mapTx;
|
||||||
|
std::map<COutPoint, CInPoint> mapNextTx;
|
||||||
|
|
||||||
|
bool accept(CTxDB& txdb, CTransaction &tx,
|
||||||
|
bool fCheckInputs, bool* pfMissingInputs);
|
||||||
|
bool addUnchecked(CTransaction &tx);
|
||||||
|
bool remove(CTransaction &tx);
|
||||||
|
|
||||||
|
unsigned long size()
|
||||||
|
{
|
||||||
|
LOCK(cs);
|
||||||
|
return mapTx.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool exists(uint256 hash)
|
||||||
|
{
|
||||||
|
return (mapTx.count(hash) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
CTransaction& lookup(uint256 hash)
|
||||||
|
{
|
||||||
|
return mapTx[hash];
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
extern CTxMemPool mempool;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in a new issue