aboutsummaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp107
1 files changed, 30 insertions, 77 deletions
diff --git a/src/main.cpp b/src/main.cpp
index e2bed5278..24e1c2334 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -31,6 +31,7 @@ CTxMemPool mempool;
unsigned int nTransactionsUpdated = 0;
map<uint256, CBlockIndex*> mapBlockIndex;
+std::vector<CBlockIndex*> vBlockIndexByHeight;
uint256 hashGenesisBlock("0x000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f");
static CBigNum bnProofOfWorkLimit(~uint256(0) >> 32);
CBlockIndex* pindexGenesisBlock = NULL;
@@ -1036,19 +1037,9 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
static CBlockIndex* pblockindexFBBHLast;
CBlockIndex* FindBlockByHeight(int nHeight)
{
- CBlockIndex *pblockindex;
- if (nHeight < nBestHeight / 2)
- pblockindex = pindexGenesisBlock;
- else
- pblockindex = pindexBest;
- if (pblockindexFBBHLast && abs(nHeight - pblockindex->nHeight) > abs(nHeight - pblockindexFBBHLast->nHeight))
- pblockindex = pblockindexFBBHLast;
- while (pblockindex->nHeight > nHeight)
- pblockindex = pblockindex->pprev;
- while (pblockindex->nHeight < nHeight)
- pblockindex = pblockindex->pnext;
- pblockindexFBBHLast = pblockindex;
- return pblockindex;
+ if (nHeight >= (int)vBlockIndexByHeight.size())
+ return NULL;
+ return vBlockIndexByHeight[nHeight];
}
bool CBlock::ReadFromDisk(const CBlockIndex* pindex)
@@ -1231,7 +1222,7 @@ void static InvalidBlockFound(CBlockIndex *pindex) {
pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex));
setBlockIndexValid.erase(pindex);
InvalidChainFound(pindex);
- if (pindex->pnext) {
+ if (pindex->GetNextInMainChain()) {
CValidationState stateDummy;
ConnectBestBlock(stateDummy); // reorganise away from the failed block
}
@@ -1271,7 +1262,7 @@ bool ConnectBestBlock(CValidationState &state) {
if (pindexBest == NULL || pindexTest->nChainWork > pindexBest->nChainWork)
vAttach.push_back(pindexTest);
- if (pindexTest->pprev == NULL || pindexTest->pnext != NULL) {
+ if (pindexTest->pprev == NULL || pindexTest->GetNextInMainChain()) {
reverse(vAttach.begin(), vAttach.end());
BOOST_FOREACH(CBlockIndex *pindexSwitch, vAttach) {
boost::this_thread::interruption_point();
@@ -1342,7 +1333,7 @@ unsigned int CTransaction::GetP2SHSigOpCount(CCoinsViewCache& inputs) const
return nSigOps;
}
-bool CTransaction::UpdateCoins(CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash) const
+void CTransaction::UpdateCoins(CValidationState &state, CCoinsViewCache &inputs, CTxUndo &txundo, int nHeight, const uint256 &txhash) const
{
// mark inputs spent
if (!IsCoinBase()) {
@@ -1356,8 +1347,6 @@ bool CTransaction::UpdateCoins(CValidationState &state, CCoinsViewCache &inputs,
// add outputs
assert(inputs.SetCoins(txhash, CCoins(*this, nHeight)));
-
- return true;
}
bool CTransaction::HaveInputs(CCoinsViewCache &inputs) const
@@ -1683,8 +1672,7 @@ bool CBlock::ConnectBlock(CValidationState &state, CBlockIndex* pindex, CCoinsVi
}
CTxUndo txundo;
- if (!tx.UpdateCoins(state, view, txundo, pindex->nHeight, GetTxHash(i)))
- return error("ConnectBlock() : UpdateInputs failed");
+ tx.UpdateCoins(state, view, txundo, pindex->nHeight, GetTxHash(i));
if (!tx.IsCoinBase())
blockundo.vtxundo.push_back(txundo);
@@ -1849,15 +1837,10 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
// At this point, all changes have been done to the database.
// Proceed by updating the memory structures.
- // Disconnect shorter branch
- BOOST_FOREACH(CBlockIndex* pindex, vDisconnect)
- if (pindex->pprev)
- pindex->pprev->pnext = NULL;
-
- // Connect longer branch
+ // Register new best chain
+ vBlockIndexByHeight.resize(pindexNew->nHeight + 1);
BOOST_FOREACH(CBlockIndex* pindex, vConnect)
- if (pindex->pprev)
- pindex->pprev->pnext = pindex;
+ vBlockIndexByHeight[pindex->nHeight] = pindex;
// Resurrect memory transactions that were in the disconnected branch
BOOST_FOREACH(CTransaction& tx, vResurrect) {
@@ -1873,7 +1856,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
}
// Update best block in wallet (so we can detect restored wallets)
- if (!fIsInitialDownload)
+ if ((pindexNew->nHeight % 20160) == 0 || (!fIsInitialDownload && (pindexNew->nHeight % 144) == 0))
{
const CBlockLocator locator(pindexNew);
::SetBestChain(locator);
@@ -2076,25 +2059,6 @@ bool CBlock::CheckBlock(CValidationState &state, bool fCheckPOW, bool fCheckMerk
if (vtx.empty() || vtx.size() > MAX_BLOCK_SIZE || ::GetSerializeSize(*this, SER_NETWORK, PROTOCOL_VERSION) > MAX_BLOCK_SIZE)
return state.DoS(100, error("CheckBlock() : size limits failed"));
- // Special short-term limits to avoid 10,000 BDB lock limit:
- if (GetBlockTime() >= 1363867200 && // start enforcing 21 March 2013, noon GMT
- GetBlockTime() < 1368576000) // stop enforcing 15 May 2013 00:00:00
- {
- // Rule is: #unique txids referenced <= 4,500
- // ... to prevent 10,000 BDB lock exhaustion on old clients
- set<uint256> setTxIn;
- for (size_t i = 0; i < vtx.size(); i++)
- {
- setTxIn.insert(vtx[i].GetHash());
- if (i == 0) continue; // skip coinbase txin
- BOOST_FOREACH(const CTxIn& txin, vtx[i].vin)
- setTxIn.insert(txin.prevout.hash);
- }
- size_t nTxids = setTxIn.size();
- if (nTxids > 4500)
- return error("CheckBlock() : 15 May maxlocks violation");
- }
-
// Check proof of work matches claimed amount
if (fCheckPOW && !CheckProofOfWork(GetHash(), nBits))
return state.DoS(50, error("CheckBlock() : proof of work failed"));
@@ -2609,12 +2573,12 @@ bool static LoadBlockIndexDB()
nBestHeight = pindexBest->nHeight;
nBestChainWork = pindexBest->nChainWork;
- // set 'next' pointers in best chain
+ // register best chain
CBlockIndex *pindex = pindexBest;
- while(pindex != NULL && pindex->pprev != NULL) {
- CBlockIndex *pindexPrev = pindex->pprev;
- pindexPrev->pnext = pindex;
- pindex = pindexPrev;
+ vBlockIndexByHeight.resize(pindexBest->nHeight + 1);
+ while(pindex != NULL) {
+ vBlockIndexByHeight[pindex->nHeight] = pindex;
+ pindex = pindex->pprev;
}
printf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s\n",
hashBestChain.ToString().c_str(), nBestHeight,
@@ -2683,7 +2647,7 @@ bool VerifyDB() {
CBlockIndex *pindex = pindexState;
while (pindex != pindexBest) {
boost::this_thread::interruption_point();
- pindex = pindex->pnext;
+ pindex = pindex->GetNextInMainChain();
CBlock block;
if (!block.ReadFromDisk(pindex))
return error("VerifyDB() : *** block.ReadFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
@@ -2859,7 +2823,7 @@ void PrintBlockTree()
vector<CBlockIndex*>& vNext = mapNext[pindex];
for (unsigned int i = 0; i < vNext.size(); i++)
{
- if (vNext[i]->pnext)
+ if (vNext[i]->GetNextInMainChain())
{
swap(vNext[0], vNext[i]);
break;
@@ -3440,10 +3404,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Send the rest of the chain
if (pindex)
- pindex = pindex->pnext;
+ pindex = pindex->GetNextInMainChain();
int nLimit = 500;
printf("getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str(), nLimit);
- for (; pindex; pindex = pindex->pnext)
+ for (; pindex; pindex = pindex->GetNextInMainChain())
{
if (pindex->GetBlockHash() == hashStop)
{
@@ -3483,14 +3447,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
// Find the last block the caller has in the main chain
pindex = locator.GetBlockIndex();
if (pindex)
- pindex = pindex->pnext;
+ pindex = pindex->GetNextInMainChain();
}
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
vector<CBlock> vHeaders;
int nLimit = 2000;
printf("getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str());
- for (; pindex; pindex = pindex->pnext)
+ for (; pindex; pindex = pindex->GetNextInMainChain())
{
vHeaders.push_back(pindex->GetBlockHeader());
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
@@ -4191,10 +4155,6 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
// Limit to betweeen 1K and MAX_BLOCK_SIZE-1K for sanity:
nBlockMaxSize = std::max((unsigned int)1000, std::min((unsigned int)(MAX_BLOCK_SIZE-1000), nBlockMaxSize));
- // Special compatibility rule before 15 May: limit size to 500,000 bytes:
- if (GetAdjustedTime() < 1368576000)
- nBlockMaxSize = std::min(nBlockMaxSize, (unsigned int)(MAX_BLOCK_SIZE_GEN));
-
// How much of the block should be dedicated to high-priority transactions,
// included regardless of the fees they pay
unsigned int nBlockPrioritySize = GetArg("-blockprioritysize", 27000);
@@ -4233,8 +4193,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
BOOST_FOREACH(const CTxIn& txin, tx.vin)
{
// Read prev transaction
- CCoins coins;
- if (!view.GetCoins(txin.prevout.hash, coins))
+ if (!view.HaveCoins(txin.prevout.hash))
{
// This should never happen; all transactions in the memory
// pool should connect to either transactions in the chain
@@ -4261,6 +4220,7 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
nTotalIn += mempool.mapTx[txin.prevout.hash].vout[txin.prevout.n].nValue;
continue;
}
+ const CCoins &coins = view.GetCoins(txin.prevout.hash);
int64 nValueIn = coins.vout[txin.prevout.n].nValue;
nTotalIn += nValueIn;
@@ -4308,9 +4268,6 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
std::pop_heap(vecPriority.begin(), vecPriority.end(), comparer);
vecPriority.pop_back();
- // second layer cached modifications just for this transaction
- CCoinsViewCache viewTemp(view, true);
-
// Size limits
unsigned int nTxSize = ::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION);
if (nBlockSize + nTxSize >= nBlockMaxSize)
@@ -4335,26 +4292,22 @@ CBlockTemplate* CreateNewBlock(CReserveKey& reservekey)
std::make_heap(vecPriority.begin(), vecPriority.end(), comparer);
}
- if (!tx.HaveInputs(viewTemp))
+ if (!tx.HaveInputs(view))
continue;
- int64 nTxFees = tx.GetValueIn(viewTemp)-tx.GetValueOut();
+ int64 nTxFees = tx.GetValueIn(view)-tx.GetValueOut();
- nTxSigOps += tx.GetP2SHSigOpCount(viewTemp);
+ nTxSigOps += tx.GetP2SHSigOpCount(view);
if (nBlockSigOps + nTxSigOps >= MAX_BLOCK_SIGOPS)
continue;
CValidationState state;
- if (!tx.CheckInputs(state, viewTemp, true, SCRIPT_VERIFY_P2SH))
+ if (!tx.CheckInputs(state, view, true, SCRIPT_VERIFY_P2SH))
continue;
CTxUndo txundo;
uint256 hash = tx.GetHash();
- if (!tx.UpdateCoins(state, viewTemp, txundo, pindexPrev->nHeight+1, hash))
- continue;
-
- // push changes from the second layer cache to the first one
- viewTemp.Flush();
+ tx.UpdateCoins(state, view, txundo, pindexPrev->nHeight+1, hash);
// Added
pblock->vtx.push_back(tx);