Merge pull request #3077 from sipa/chain
Refactor/encapsulate chain globals into a CChain class
This commit is contained in:
commit
b9beea6e9d
19 changed files with 217 additions and 213 deletions
20
src/init.cpp
20
src/init.cpp
|
@ -116,7 +116,7 @@ void Shutdown()
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
if (pwalletMain)
|
if (pwalletMain)
|
||||||
pwalletMain->SetBestChain(CBlockLocator(pindexBest));
|
pwalletMain->SetBestChain(CBlockLocator(chainActive.Tip()));
|
||||||
if (pblocktree)
|
if (pblocktree)
|
||||||
pblocktree->Flush();
|
pblocktree->Flush();
|
||||||
if (pcoinsTip)
|
if (pcoinsTip)
|
||||||
|
@ -766,7 +766,7 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||||
|
|
||||||
// If the loaded chain has a wrong genesis, bail out immediately
|
// If the loaded chain has a wrong genesis, bail out immediately
|
||||||
// (we're likely using a testnet datadir, or the other way around).
|
// (we're likely using a testnet datadir, or the other way around).
|
||||||
if (!mapBlockIndex.empty() && pindexGenesisBlock == NULL)
|
if (!mapBlockIndex.empty() && chainActive.Genesis() == NULL)
|
||||||
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
|
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
|
||||||
|
|
||||||
// Initialize the block index (no-op if non-empty database was already loaded)
|
// Initialize the block index (no-op if non-empty database was already loaded)
|
||||||
|
@ -912,7 +912,7 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||||
strErrors << _("Cannot write default address") << "\n";
|
strErrors << _("Cannot write default address") << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
pwalletMain->SetBestChain(CBlockLocator(pindexBest));
|
pwalletMain->SetBestChain(CBlockLocator(chainActive.Tip()));
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrintf("%s", strErrors.str().c_str());
|
LogPrintf("%s", strErrors.str().c_str());
|
||||||
|
@ -920,9 +920,9 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||||
|
|
||||||
RegisterWallet(pwalletMain);
|
RegisterWallet(pwalletMain);
|
||||||
|
|
||||||
CBlockIndex *pindexRescan = pindexBest;
|
CBlockIndex *pindexRescan = chainActive.Tip();
|
||||||
if (GetBoolArg("-rescan", false))
|
if (GetBoolArg("-rescan", false))
|
||||||
pindexRescan = pindexGenesisBlock;
|
pindexRescan = chainActive.Genesis();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CWalletDB walletdb(strWalletFile);
|
CWalletDB walletdb(strWalletFile);
|
||||||
|
@ -930,16 +930,16 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||||
if (walletdb.ReadBestBlock(locator))
|
if (walletdb.ReadBestBlock(locator))
|
||||||
pindexRescan = locator.GetBlockIndex();
|
pindexRescan = locator.GetBlockIndex();
|
||||||
else
|
else
|
||||||
pindexRescan = pindexGenesisBlock;
|
pindexRescan = chainActive.Genesis();
|
||||||
}
|
}
|
||||||
if (pindexBest && pindexBest != pindexRescan)
|
if (chainActive.Tip() && chainActive.Tip() != pindexRescan)
|
||||||
{
|
{
|
||||||
uiInterface.InitMessage(_("Rescanning..."));
|
uiInterface.InitMessage(_("Rescanning..."));
|
||||||
LogPrintf("Rescanning last %i blocks (from block %i)...\n", pindexBest->nHeight - pindexRescan->nHeight, pindexRescan->nHeight);
|
LogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
|
||||||
nStart = GetTimeMillis();
|
nStart = GetTimeMillis();
|
||||||
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
|
pwalletMain->ScanForWalletTransactions(pindexRescan, true);
|
||||||
LogPrintf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
LogPrintf(" rescan %15"PRI64d"ms\n", GetTimeMillis() - nStart);
|
||||||
pwalletMain->SetBestChain(CBlockLocator(pindexBest));
|
pwalletMain->SetBestChain(CBlockLocator(chainActive.Tip()));
|
||||||
nWalletDBUpdated++;
|
nWalletDBUpdated++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -985,7 +985,7 @@ bool AppInit2(boost::thread_group& threadGroup)
|
||||||
|
|
||||||
//// debug print
|
//// debug print
|
||||||
LogPrintf("mapBlockIndex.size() = %"PRIszu"\n", mapBlockIndex.size());
|
LogPrintf("mapBlockIndex.size() = %"PRIszu"\n", mapBlockIndex.size());
|
||||||
LogPrintf("nBestHeight = %d\n", nBestHeight);
|
LogPrintf("nBestHeight = %d\n", chainActive.Height());
|
||||||
LogPrintf("setKeyPool.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0);
|
LogPrintf("setKeyPool.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->setKeyPool.size() : 0);
|
||||||
LogPrintf("mapWallet.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapWallet.size() : 0);
|
LogPrintf("mapWallet.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapWallet.size() : 0);
|
||||||
LogPrintf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0);
|
LogPrintf("mapAddressBook.size() = %"PRIszu"\n", pwalletMain ? pwalletMain->mapAddressBook.size() : 0);
|
||||||
|
|
191
src/main.cpp
191
src/main.cpp
|
@ -32,13 +32,8 @@ CTxMemPool mempool;
|
||||||
unsigned int nTransactionsUpdated = 0;
|
unsigned int nTransactionsUpdated = 0;
|
||||||
|
|
||||||
map<uint256, CBlockIndex*> mapBlockIndex;
|
map<uint256, CBlockIndex*> mapBlockIndex;
|
||||||
std::vector<CBlockIndex*> vBlockIndexByHeight;
|
CChain chainActive;
|
||||||
CBlockIndex* pindexGenesisBlock = NULL;
|
|
||||||
int nBestHeight = -1;
|
|
||||||
uint256 nBestChainWork = 0;
|
|
||||||
uint256 nBestInvalidWork = 0;
|
uint256 nBestInvalidWork = 0;
|
||||||
uint256 hashBestChain = 0;
|
|
||||||
CBlockIndex* pindexBest = NULL;
|
|
||||||
set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid; // may contain all CBlockIndex*'s that have validness >=BLOCK_VALID_TRANSACTIONS, and must contain those who aren't failed
|
set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid; // may contain all CBlockIndex*'s that have validness >=BLOCK_VALID_TRANSACTIONS, and must contain those who aren't failed
|
||||||
int64 nTimeBestReceived = 0;
|
int64 nTimeBestReceived = 0;
|
||||||
int nScriptCheckThreads = 0;
|
int nScriptCheckThreads = 0;
|
||||||
|
@ -173,14 +168,22 @@ void static ResendWalletTransactions()
|
||||||
// Registration of network node signals.
|
// Registration of network node signals.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
int static GetHeight()
|
||||||
|
{
|
||||||
|
LOCK(cs_main);
|
||||||
|
return chainActive.Height();
|
||||||
|
}
|
||||||
|
|
||||||
void RegisterNodeSignals(CNodeSignals& nodeSignals)
|
void RegisterNodeSignals(CNodeSignals& nodeSignals)
|
||||||
{
|
{
|
||||||
|
nodeSignals.GetHeight.connect(&GetHeight);
|
||||||
nodeSignals.ProcessMessages.connect(&ProcessMessages);
|
nodeSignals.ProcessMessages.connect(&ProcessMessages);
|
||||||
nodeSignals.SendMessages.connect(&SendMessages);
|
nodeSignals.SendMessages.connect(&SendMessages);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UnregisterNodeSignals(CNodeSignals& nodeSignals)
|
void UnregisterNodeSignals(CNodeSignals& nodeSignals)
|
||||||
{
|
{
|
||||||
|
nodeSignals.GetHeight.disconnect(&GetHeight);
|
||||||
nodeSignals.ProcessMessages.disconnect(&ProcessMessages);
|
nodeSignals.ProcessMessages.disconnect(&ProcessMessages);
|
||||||
nodeSignals.SendMessages.disconnect(&SendMessages);
|
nodeSignals.SendMessages.disconnect(&SendMessages);
|
||||||
}
|
}
|
||||||
|
@ -225,7 +228,7 @@ int CBlockLocator::GetDistanceBack()
|
||||||
if (mi != mapBlockIndex.end())
|
if (mi != mapBlockIndex.end())
|
||||||
{
|
{
|
||||||
CBlockIndex* pindex = (*mi).second;
|
CBlockIndex* pindex = (*mi).second;
|
||||||
if (pindex->IsInMainChain())
|
if (chainActive.Contains(pindex))
|
||||||
return nDistance;
|
return nDistance;
|
||||||
}
|
}
|
||||||
nDistance += nStep;
|
nDistance += nStep;
|
||||||
|
@ -244,11 +247,11 @@ CBlockIndex *CBlockLocator::GetBlockIndex()
|
||||||
if (mi != mapBlockIndex.end())
|
if (mi != mapBlockIndex.end())
|
||||||
{
|
{
|
||||||
CBlockIndex* pindex = (*mi).second;
|
CBlockIndex* pindex = (*mi).second;
|
||||||
if (pindex->IsInMainChain())
|
if (chainActive.Contains(pindex))
|
||||||
return pindex;
|
return pindex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return pindexGenesisBlock;
|
return chainActive.Genesis();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 CBlockLocator::GetBlockHash()
|
uint256 CBlockLocator::GetBlockHash()
|
||||||
|
@ -260,7 +263,7 @@ uint256 CBlockLocator::GetBlockHash()
|
||||||
if (mi != mapBlockIndex.end())
|
if (mi != mapBlockIndex.end())
|
||||||
{
|
{
|
||||||
CBlockIndex* pindex = (*mi).second;
|
CBlockIndex* pindex = (*mi).second;
|
||||||
if (pindex->IsInMainChain())
|
if (chainActive.Contains(pindex))
|
||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -275,6 +278,19 @@ int CBlockLocator::GetHeight()
|
||||||
return pindex->nHeight;
|
return pindex->nHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CBlockIndex *CChain::SetTip(CBlockIndex *pindex) {
|
||||||
|
if (pindex == NULL) {
|
||||||
|
std::vector<CBlockIndex*>().swap(vChain);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
vChain.resize(pindex->nHeight + 1);
|
||||||
|
while (pindex && vChain[pindex->nHeight] != pindex) {
|
||||||
|
vChain[pindex->nHeight] = pindex;
|
||||||
|
pindex = pindex->pprev;
|
||||||
|
}
|
||||||
|
return pindex;
|
||||||
|
}
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// CCoinsView implementations
|
// CCoinsView implementations
|
||||||
|
@ -517,7 +533,7 @@ bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64 nBlockTime)
|
||||||
if (tx.nLockTime == 0)
|
if (tx.nLockTime == 0)
|
||||||
return true;
|
return true;
|
||||||
if (nBlockHeight == 0)
|
if (nBlockHeight == 0)
|
||||||
nBlockHeight = nBestHeight;
|
nBlockHeight = chainActive.Height();
|
||||||
if (nBlockTime == 0)
|
if (nBlockTime == 0)
|
||||||
nBlockTime = GetAdjustedTime();
|
nBlockTime = GetAdjustedTime();
|
||||||
if ((int64)tx.nLockTime < ((int64)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
|
if ((int64)tx.nLockTime < ((int64)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
|
||||||
|
@ -644,7 +660,7 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
|
||||||
if (pblock == NULL) {
|
if (pblock == NULL) {
|
||||||
CCoins coins;
|
CCoins coins;
|
||||||
if (pcoinsTip->GetCoins(GetHash(), coins)) {
|
if (pcoinsTip->GetCoins(GetHash(), coins)) {
|
||||||
CBlockIndex *pindex = FindBlockByHeight(coins.nHeight);
|
CBlockIndex *pindex = chainActive[coins.nHeight];
|
||||||
if (pindex) {
|
if (pindex) {
|
||||||
if (!ReadBlockFromDisk(blockTmp, pindex))
|
if (!ReadBlockFromDisk(blockTmp, pindex))
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -678,10 +694,10 @@ int CMerkleTx::SetMerkleBranch(const CBlock* pblock)
|
||||||
if (mi == mapBlockIndex.end())
|
if (mi == mapBlockIndex.end())
|
||||||
return 0;
|
return 0;
|
||||||
CBlockIndex* pindex = (*mi).second;
|
CBlockIndex* pindex = (*mi).second;
|
||||||
if (!pindex || !pindex->IsInMainChain())
|
if (!pindex || !chainActive.Contains(pindex))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return pindexBest->nHeight - pindex->nHeight + 1;
|
return chainActive.Height() - pindex->nHeight + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1078,7 +1094,7 @@ int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
|
||||||
if (mi == mapBlockIndex.end())
|
if (mi == mapBlockIndex.end())
|
||||||
return 0;
|
return 0;
|
||||||
CBlockIndex* pindex = (*mi).second;
|
CBlockIndex* pindex = (*mi).second;
|
||||||
if (!pindex || !pindex->IsInMainChain())
|
if (!pindex || !chainActive.Contains(pindex))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
// Make sure the merkle branch connects to this block
|
// Make sure the merkle branch connects to this block
|
||||||
|
@ -1090,7 +1106,7 @@ int CMerkleTx::GetDepthInMainChain(CBlockIndex* &pindexRet) const
|
||||||
}
|
}
|
||||||
|
|
||||||
pindexRet = pindex;
|
pindexRet = pindex;
|
||||||
return pindexBest->nHeight - pindex->nHeight + 1;
|
return chainActive.Height() - pindex->nHeight + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1173,7 +1189,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
|
||||||
nHeight = coins.nHeight;
|
nHeight = coins.nHeight;
|
||||||
}
|
}
|
||||||
if (nHeight > 0)
|
if (nHeight > 0)
|
||||||
pindexSlow = FindBlockByHeight(nHeight);
|
pindexSlow = chainActive[nHeight];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1203,14 +1219,6 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, uint256 &hashBlock
|
||||||
// CBlock and CBlockIndex
|
// CBlock and CBlockIndex
|
||||||
//
|
//
|
||||||
|
|
||||||
static CBlockIndex* pblockindexFBBHLast;
|
|
||||||
CBlockIndex* FindBlockByHeight(int nHeight)
|
|
||||||
{
|
|
||||||
if (nHeight >= (int)vBlockIndexByHeight.size())
|
|
||||||
return NULL;
|
|
||||||
return vBlockIndexByHeight[nHeight];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos)
|
bool WriteBlockToDisk(CBlock& block, CDiskBlockPos& pos)
|
||||||
{
|
{
|
||||||
// Open history file to append
|
// Open history file to append
|
||||||
|
@ -1404,17 +1412,17 @@ int GetNumBlocksOfPeers()
|
||||||
|
|
||||||
bool IsInitialBlockDownload()
|
bool IsInitialBlockDownload()
|
||||||
{
|
{
|
||||||
if (pindexBest == NULL || fImporting || fReindex || nBestHeight < Checkpoints::GetTotalBlocksEstimate())
|
if (fImporting || fReindex || chainActive.Height() < Checkpoints::GetTotalBlocksEstimate())
|
||||||
return true;
|
return true;
|
||||||
static int64 nLastUpdate;
|
static int64 nLastUpdate;
|
||||||
static CBlockIndex* pindexLastBest;
|
static CBlockIndex* pindexLastBest;
|
||||||
if (pindexBest != pindexLastBest)
|
if (chainActive.Tip() != pindexLastBest)
|
||||||
{
|
{
|
||||||
pindexLastBest = pindexBest;
|
pindexLastBest = chainActive.Tip();
|
||||||
nLastUpdate = GetTime();
|
nLastUpdate = GetTime();
|
||||||
}
|
}
|
||||||
return (GetTime() - nLastUpdate < 10 &&
|
return (GetTime() - nLastUpdate < 10 &&
|
||||||
pindexBest->GetBlockTime() < GetTime() - 24 * 60 * 60);
|
chainActive.Tip()->GetBlockTime() < GetTime() - 24 * 60 * 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool fLargeWorkForkFound = false;
|
bool fLargeWorkForkFound = false;
|
||||||
|
@ -1430,10 +1438,10 @@ void CheckForkWarningConditions()
|
||||||
|
|
||||||
// If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it)
|
// If our best fork is no longer within 72 blocks (+/- 12 hours if no one mines it)
|
||||||
// of our head, drop it
|
// of our head, drop it
|
||||||
if (pindexBestForkTip && nBestHeight - pindexBestForkTip->nHeight >= 72)
|
if (pindexBestForkTip && chainActive.Height() - pindexBestForkTip->nHeight >= 72)
|
||||||
pindexBestForkTip = NULL;
|
pindexBestForkTip = NULL;
|
||||||
|
|
||||||
if (pindexBestForkTip || nBestInvalidWork > nBestChainWork + (pindexBest->GetBlockWork() * 6).getuint256())
|
if (pindexBestForkTip || nBestInvalidWork > chainActive.Tip()->nChainWork + (chainActive.Tip()->GetBlockWork() * 6).getuint256())
|
||||||
{
|
{
|
||||||
if (!fLargeWorkForkFound)
|
if (!fLargeWorkForkFound)
|
||||||
{
|
{
|
||||||
|
@ -1470,7 +1478,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
|
||||||
{
|
{
|
||||||
// If we are on a fork that is sufficiently large, set a warning flag
|
// If we are on a fork that is sufficiently large, set a warning flag
|
||||||
CBlockIndex* pfork = pindexNewForkTip;
|
CBlockIndex* pfork = pindexNewForkTip;
|
||||||
CBlockIndex* plonger = pindexBest;
|
CBlockIndex* plonger = chainActive.Tip();
|
||||||
while (pfork && pfork != plonger)
|
while (pfork && pfork != plonger)
|
||||||
{
|
{
|
||||||
while (plonger && plonger->nHeight > pfork->nHeight)
|
while (plonger && plonger->nHeight > pfork->nHeight)
|
||||||
|
@ -1489,7 +1497,7 @@ void CheckForkWarningConditionsOnNewFork(CBlockIndex* pindexNewForkTip)
|
||||||
// the 7-block condition and from this always have the most-likely-to-cause-warning fork
|
// the 7-block condition and from this always have the most-likely-to-cause-warning fork
|
||||||
if (pfork && (!pindexBestForkTip || (pindexBestForkTip && pindexNewForkTip->nHeight > pindexBestForkTip->nHeight)) &&
|
if (pfork && (!pindexBestForkTip || (pindexBestForkTip && pindexNewForkTip->nHeight > pindexBestForkTip->nHeight)) &&
|
||||||
pindexNewForkTip->nChainWork - pfork->nChainWork > (pfork->GetBlockWork() * 7).getuint256() &&
|
pindexNewForkTip->nChainWork - pfork->nChainWork > (pfork->GetBlockWork() * 7).getuint256() &&
|
||||||
nBestHeight - pindexNewForkTip->nHeight < 72)
|
chainActive.Height() - pindexNewForkTip->nHeight < 72)
|
||||||
{
|
{
|
||||||
pindexBestForkTip = pindexNewForkTip;
|
pindexBestForkTip = pindexNewForkTip;
|
||||||
pindexBestForkBase = pfork;
|
pindexBestForkBase = pfork;
|
||||||
|
@ -1511,8 +1519,8 @@ void static InvalidChainFound(CBlockIndex* pindexNew)
|
||||||
log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S",
|
log(pindexNew->nChainWork.getdouble())/log(2.0), DateTimeStrFormat("%Y-%m-%d %H:%M:%S",
|
||||||
pindexNew->GetBlockTime()).c_str());
|
pindexNew->GetBlockTime()).c_str());
|
||||||
LogPrintf("InvalidChainFound: current best=%s height=%d log2_work=%.8g date=%s\n",
|
LogPrintf("InvalidChainFound: current best=%s height=%d log2_work=%.8g date=%s\n",
|
||||||
hashBestChain.ToString().c_str(), nBestHeight, log(nBestChainWork.getdouble())/log(2.0),
|
chainActive.Tip()->GetBlockHash().ToString().c_str(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0),
|
||||||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str());
|
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str());
|
||||||
CheckForkWarningConditions();
|
CheckForkWarningConditions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1521,7 +1529,7 @@ void static InvalidBlockFound(CBlockIndex *pindex) {
|
||||||
pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex));
|
pblocktree->WriteBlockIndex(CDiskBlockIndex(pindex));
|
||||||
setBlockIndexValid.erase(pindex);
|
setBlockIndexValid.erase(pindex);
|
||||||
InvalidChainFound(pindex);
|
InvalidChainFound(pindex);
|
||||||
if (pindex->GetNextInMainChain()) {
|
if (chainActive.Next(pindex)) {
|
||||||
CValidationState stateDummy;
|
CValidationState stateDummy;
|
||||||
ConnectBestBlock(stateDummy); // reorganise away from the failed block
|
ConnectBestBlock(stateDummy); // reorganise away from the failed block
|
||||||
}
|
}
|
||||||
|
@ -1538,7 +1546,7 @@ bool ConnectBestBlock(CValidationState &state) {
|
||||||
pindexNewBest = *it;
|
pindexNewBest = *it;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pindexNewBest == pindexBest || (pindexBest && pindexNewBest->nChainWork == pindexBest->nChainWork))
|
if (pindexNewBest == chainActive.Tip() || (chainActive.Tip() && pindexNewBest->nChainWork == chainActive.Tip()->nChainWork))
|
||||||
return true; // nothing to do
|
return true; // nothing to do
|
||||||
|
|
||||||
// check ancestry
|
// check ancestry
|
||||||
|
@ -1558,10 +1566,10 @@ bool ConnectBestBlock(CValidationState &state) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pindexBest == NULL || pindexTest->nChainWork > pindexBest->nChainWork)
|
if (chainActive.Tip() == NULL || pindexTest->nChainWork > chainActive.Tip()->nChainWork)
|
||||||
vAttach.push_back(pindexTest);
|
vAttach.push_back(pindexTest);
|
||||||
|
|
||||||
if (pindexTest->pprev == NULL || pindexTest->GetNextInMainChain()) {
|
if (pindexTest->pprev == NULL || chainActive.Next(pindexTest)) {
|
||||||
reverse(vAttach.begin(), vAttach.end());
|
reverse(vAttach.begin(), vAttach.end());
|
||||||
BOOST_FOREACH(CBlockIndex *pindexSwitch, vAttach) {
|
BOOST_FOREACH(CBlockIndex *pindexSwitch, vAttach) {
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
|
@ -1881,7 +1889,6 @@ bool ConnectBlock(CBlock& block, CValidationState& state, CBlockIndex* pindex, C
|
||||||
// (its coinbase is unspendable)
|
// (its coinbase is unspendable)
|
||||||
if (block.GetHash() == Params().HashGenesisBlock()) {
|
if (block.GetHash() == Params().HashGenesisBlock()) {
|
||||||
view.SetBestBlock(pindex);
|
view.SetBestBlock(pindex);
|
||||||
pindexGenesisBlock = pindex;
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2129,9 +2136,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
|
||||||
// Proceed by updating the memory structures.
|
// Proceed by updating the memory structures.
|
||||||
|
|
||||||
// Register new best chain
|
// Register new best chain
|
||||||
vBlockIndexByHeight.resize(pindexNew->nHeight + 1);
|
chainActive.SetTip(pindexNew);
|
||||||
BOOST_FOREACH(CBlockIndex* pindex, vConnect)
|
|
||||||
vBlockIndexByHeight[pindex->nHeight] = pindex;
|
|
||||||
|
|
||||||
// Resurrect memory transactions that were in the disconnected branch
|
// Resurrect memory transactions that were in the disconnected branch
|
||||||
BOOST_FOREACH(CTransaction& tx, vResurrect) {
|
BOOST_FOREACH(CTransaction& tx, vResurrect) {
|
||||||
|
@ -2157,23 +2162,18 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
|
||||||
}
|
}
|
||||||
|
|
||||||
// New best block
|
// New best block
|
||||||
hashBestChain = pindexNew->GetBlockHash();
|
|
||||||
pindexBest = pindexNew;
|
|
||||||
pblockindexFBBHLast = NULL;
|
|
||||||
nBestHeight = pindexBest->nHeight;
|
|
||||||
nBestChainWork = pindexNew->nChainWork;
|
|
||||||
nTimeBestReceived = GetTime();
|
nTimeBestReceived = GetTime();
|
||||||
nTransactionsUpdated++;
|
nTransactionsUpdated++;
|
||||||
LogPrintf("SetBestChain: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f\n",
|
LogPrintf("SetBestChain: new best=%s height=%d log2_work=%.8g tx=%lu date=%s progress=%f\n",
|
||||||
hashBestChain.ToString().c_str(), nBestHeight, log(nBestChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx,
|
chainActive.Tip()->GetBlockHash().ToString().c_str(), chainActive.Height(), log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx,
|
||||||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str(),
|
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str(),
|
||||||
Checkpoints::GuessVerificationProgress(pindexBest));
|
Checkpoints::GuessVerificationProgress(chainActive.Tip()));
|
||||||
|
|
||||||
// Check the version of the last 100 blocks to see if we need to upgrade:
|
// Check the version of the last 100 blocks to see if we need to upgrade:
|
||||||
if (!fIsInitialDownload)
|
if (!fIsInitialDownload)
|
||||||
{
|
{
|
||||||
int nUpgraded = 0;
|
int nUpgraded = 0;
|
||||||
const CBlockIndex* pindex = pindexBest;
|
const CBlockIndex* pindex = chainActive.Tip();
|
||||||
for (int i = 0; i < 100 && pindex != NULL; i++)
|
for (int i = 0; i < 100 && pindex != NULL; i++)
|
||||||
{
|
{
|
||||||
if (pindex->nVersion > CBlock::CURRENT_VERSION)
|
if (pindex->nVersion > CBlock::CURRENT_VERSION)
|
||||||
|
@ -2191,7 +2191,7 @@ bool SetBestChain(CValidationState &state, CBlockIndex* pindexNew)
|
||||||
|
|
||||||
if (!fIsInitialDownload && !strCmd.empty())
|
if (!fIsInitialDownload && !strCmd.empty())
|
||||||
{
|
{
|
||||||
boost::replace_all(strCmd, "%s", hashBestChain.GetHex());
|
boost::replace_all(strCmd, "%s", chainActive.Tip()->GetBlockHash().GetHex());
|
||||||
boost::thread t(runCommand, strCmd); // thread runs free
|
boost::thread t(runCommand, strCmd); // thread runs free
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2233,7 +2233,7 @@ bool AddToBlockIndex(CBlock& block, CValidationState& state, const CDiskBlockPos
|
||||||
if (!ConnectBestBlock(state))
|
if (!ConnectBestBlock(state))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (pindexNew == pindexBest)
|
if (pindexNew == chainActive.Tip())
|
||||||
{
|
{
|
||||||
// Clear fork warning if its no longer applicable
|
// Clear fork warning if its no longer applicable
|
||||||
CheckForkWarningConditions();
|
CheckForkWarningConditions();
|
||||||
|
@ -2482,11 +2482,11 @@ bool AcceptBlock(CBlock& block, CValidationState& state, CDiskBlockPos* dbp)
|
||||||
|
|
||||||
// Relay inventory, but don't relay old inventory during initial block download
|
// Relay inventory, but don't relay old inventory during initial block download
|
||||||
int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate();
|
int nBlockEstimate = Checkpoints::GetTotalBlocksEstimate();
|
||||||
if (hashBestChain == hash)
|
if (chainActive.Tip()->GetBlockHash() == hash)
|
||||||
{
|
{
|
||||||
LOCK(cs_vNodes);
|
LOCK(cs_vNodes);
|
||||||
BOOST_FOREACH(CNode* pnode, vNodes)
|
BOOST_FOREACH(CNode* pnode, vNodes)
|
||||||
if (nBestHeight > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
|
if (chainActive.Height() > (pnode->nStartingHeight != -1 ? pnode->nStartingHeight - 2000 : nBlockEstimate))
|
||||||
pnode->PushInventory(CInv(MSG_BLOCK, hash));
|
pnode->PushInventory(CInv(MSG_BLOCK, hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2505,6 +2505,18 @@ bool CBlockIndex::IsSuperMajority(int minVersion, const CBlockIndex* pstart, uns
|
||||||
return (nFound >= nRequired);
|
return (nFound >= nRequired);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64 CBlockIndex::GetMedianTime() const
|
||||||
|
{
|
||||||
|
const CBlockIndex* pindex = this;
|
||||||
|
for (int i = 0; i < nMedianTimeSpan/2; i++)
|
||||||
|
{
|
||||||
|
if (!chainActive.Next(pindex))
|
||||||
|
return GetBlockTime();
|
||||||
|
pindex = chainActive.Next(pindex);
|
||||||
|
}
|
||||||
|
return pindex->GetMedianTimePast();
|
||||||
|
}
|
||||||
|
|
||||||
void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
|
void PushGetBlocks(CNode* pnode, CBlockIndex* pindexBegin, uint256 hashEnd)
|
||||||
{
|
{
|
||||||
// Filter out duplicate requests
|
// Filter out duplicate requests
|
||||||
|
@ -2530,7 +2542,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
|
||||||
return error("ProcessBlock() : CheckBlock FAILED");
|
return error("ProcessBlock() : CheckBlock FAILED");
|
||||||
|
|
||||||
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
|
CBlockIndex* pcheckpoint = Checkpoints::GetLastCheckpoint(mapBlockIndex);
|
||||||
if (pcheckpoint && pblock->hashPrevBlock != hashBestChain)
|
if (pcheckpoint && pblock->hashPrevBlock != (chainActive.Tip() ? chainActive.Tip()->GetBlockHash() : uint256(0)))
|
||||||
{
|
{
|
||||||
// Extra checks to prevent "fill up memory by spamming with bogus blocks"
|
// Extra checks to prevent "fill up memory by spamming with bogus blocks"
|
||||||
int64 deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime;
|
int64 deltaTime = pblock->GetBlockTime() - pcheckpoint->nTime;
|
||||||
|
@ -2561,7 +2573,7 @@ bool ProcessBlock(CValidationState &state, CNode* pfrom, CBlock* pblock, CDiskBl
|
||||||
mapOrphanBlocksByPrev.insert(make_pair(pblock2->hashPrevBlock, pblock2));
|
mapOrphanBlocksByPrev.insert(make_pair(pblock2->hashPrevBlock, pblock2));
|
||||||
|
|
||||||
// Ask this guy to fill in what we're missing
|
// Ask this guy to fill in what we're missing
|
||||||
PushGetBlocks(pfrom, pindexBest, GetOrphanRoot(pblock2));
|
PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(pblock2));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2875,48 +2887,39 @@ bool static LoadBlockIndexDB()
|
||||||
LogPrintf("LoadBlockIndexDB(): transaction index %s\n", fTxIndex ? "enabled" : "disabled");
|
LogPrintf("LoadBlockIndexDB(): transaction index %s\n", fTxIndex ? "enabled" : "disabled");
|
||||||
|
|
||||||
// Load hashBestChain pointer to end of best chain
|
// Load hashBestChain pointer to end of best chain
|
||||||
pindexBest = pcoinsTip->GetBestBlock();
|
chainActive.SetTip(pcoinsTip->GetBestBlock());
|
||||||
if (pindexBest == NULL)
|
if (chainActive.Tip() == NULL)
|
||||||
return true;
|
return true;
|
||||||
hashBestChain = pindexBest->GetBlockHash();
|
|
||||||
nBestHeight = pindexBest->nHeight;
|
|
||||||
nBestChainWork = pindexBest->nChainWork;
|
|
||||||
|
|
||||||
// register best chain
|
// register best chain
|
||||||
CBlockIndex *pindex = pindexBest;
|
|
||||||
vBlockIndexByHeight.resize(pindexBest->nHeight + 1);
|
|
||||||
while(pindex != NULL) {
|
|
||||||
vBlockIndexByHeight[pindex->nHeight] = pindex;
|
|
||||||
pindex = pindex->pprev;
|
|
||||||
}
|
|
||||||
LogPrintf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s\n",
|
LogPrintf("LoadBlockIndexDB(): hashBestChain=%s height=%d date=%s\n",
|
||||||
hashBestChain.ToString().c_str(), nBestHeight,
|
chainActive.Tip()->GetBlockHash().ToString().c_str(), chainActive.Height(),
|
||||||
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexBest->GetBlockTime()).c_str());
|
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()).c_str());
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VerifyDB(int nCheckLevel, int nCheckDepth)
|
bool VerifyDB(int nCheckLevel, int nCheckDepth)
|
||||||
{
|
{
|
||||||
if (pindexBest == NULL || pindexBest->pprev == NULL)
|
if (chainActive.Tip() == NULL || chainActive.Tip()->pprev == NULL)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Verify blocks in the best chain
|
// Verify blocks in the best chain
|
||||||
if (nCheckDepth <= 0)
|
if (nCheckDepth <= 0)
|
||||||
nCheckDepth = 1000000000; // suffices until the year 19000
|
nCheckDepth = 1000000000; // suffices until the year 19000
|
||||||
if (nCheckDepth > nBestHeight)
|
if (nCheckDepth > chainActive.Height())
|
||||||
nCheckDepth = nBestHeight;
|
nCheckDepth = chainActive.Height();
|
||||||
nCheckLevel = std::max(0, std::min(4, nCheckLevel));
|
nCheckLevel = std::max(0, std::min(4, nCheckLevel));
|
||||||
LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
|
LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, nCheckLevel);
|
||||||
CCoinsViewCache coins(*pcoinsTip, true);
|
CCoinsViewCache coins(*pcoinsTip, true);
|
||||||
CBlockIndex* pindexState = pindexBest;
|
CBlockIndex* pindexState = chainActive.Tip();
|
||||||
CBlockIndex* pindexFailure = NULL;
|
CBlockIndex* pindexFailure = NULL;
|
||||||
int nGoodTransactions = 0;
|
int nGoodTransactions = 0;
|
||||||
CValidationState state;
|
CValidationState state;
|
||||||
for (CBlockIndex* pindex = pindexBest; pindex && pindex->pprev; pindex = pindex->pprev)
|
for (CBlockIndex* pindex = chainActive.Tip(); pindex && pindex->pprev; pindex = pindex->pprev)
|
||||||
{
|
{
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
if (pindex->nHeight < nBestHeight-nCheckDepth)
|
if (pindex->nHeight < chainActive.Height()-nCheckDepth)
|
||||||
break;
|
break;
|
||||||
CBlock block;
|
CBlock block;
|
||||||
// check level 0: read from disk
|
// check level 0: read from disk
|
||||||
|
@ -2948,14 +2951,14 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (pindexFailure)
|
if (pindexFailure)
|
||||||
return error("VerifyDB() : *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", pindexBest->nHeight - pindexFailure->nHeight + 1, nGoodTransactions);
|
return error("VerifyDB() : *** coin database inconsistencies found (last %i blocks, %i good transactions before that)\n", chainActive.Height() - pindexFailure->nHeight + 1, nGoodTransactions);
|
||||||
|
|
||||||
// check level 4: try reconnecting blocks
|
// check level 4: try reconnecting blocks
|
||||||
if (nCheckLevel >= 4) {
|
if (nCheckLevel >= 4) {
|
||||||
CBlockIndex *pindex = pindexState;
|
CBlockIndex *pindex = pindexState;
|
||||||
while (pindex != pindexBest) {
|
while (pindex != chainActive.Tip()) {
|
||||||
boost::this_thread::interruption_point();
|
boost::this_thread::interruption_point();
|
||||||
pindex = pindex->GetNextInMainChain();
|
pindex = chainActive.Next(pindex);
|
||||||
CBlock block;
|
CBlock block;
|
||||||
if (!ReadBlockFromDisk(block, pindex))
|
if (!ReadBlockFromDisk(block, pindex))
|
||||||
return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
|
return error("VerifyDB() : *** ReadBlockFromDisk failed at %d, hash=%s", pindex->nHeight, pindex->GetBlockHash().ToString().c_str());
|
||||||
|
@ -2964,7 +2967,7 @@ bool VerifyDB(int nCheckLevel, int nCheckDepth)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", pindexBest->nHeight - pindexState->nHeight, nGoodTransactions);
|
LogPrintf("No coin database inconsistencies in last %i blocks (%i transactions)\n", chainActive.Height() - pindexState->nHeight, nGoodTransactions);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -2973,12 +2976,8 @@ void UnloadBlockIndex()
|
||||||
{
|
{
|
||||||
mapBlockIndex.clear();
|
mapBlockIndex.clear();
|
||||||
setBlockIndexValid.clear();
|
setBlockIndexValid.clear();
|
||||||
pindexGenesisBlock = NULL;
|
chainActive.SetTip(NULL);
|
||||||
nBestHeight = 0;
|
|
||||||
nBestChainWork = 0;
|
|
||||||
nBestInvalidWork = 0;
|
nBestInvalidWork = 0;
|
||||||
hashBestChain = 0;
|
|
||||||
pindexBest = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadBlockIndex()
|
bool LoadBlockIndex()
|
||||||
|
@ -2992,7 +2991,7 @@ bool LoadBlockIndex()
|
||||||
|
|
||||||
bool InitBlockIndex() {
|
bool InitBlockIndex() {
|
||||||
// Check whether we're already initialized
|
// Check whether we're already initialized
|
||||||
if (pindexGenesisBlock != NULL)
|
if (chainActive.Genesis() != NULL)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Use the provided setting for -txindex in the new database
|
// Use the provided setting for -txindex in the new database
|
||||||
|
@ -3038,7 +3037,7 @@ void PrintBlockTree()
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<pair<int, CBlockIndex*> > vStack;
|
vector<pair<int, CBlockIndex*> > vStack;
|
||||||
vStack.push_back(make_pair(0, pindexGenesisBlock));
|
vStack.push_back(make_pair(0, chainActive.Genesis()));
|
||||||
|
|
||||||
int nPrevCol = 0;
|
int nPrevCol = 0;
|
||||||
while (!vStack.empty())
|
while (!vStack.empty())
|
||||||
|
@ -3081,7 +3080,7 @@ void PrintBlockTree()
|
||||||
vector<CBlockIndex*>& vNext = mapNext[pindex];
|
vector<CBlockIndex*>& vNext = mapNext[pindex];
|
||||||
for (unsigned int i = 0; i < vNext.size(); i++)
|
for (unsigned int i = 0; i < vNext.size(); i++)
|
||||||
{
|
{
|
||||||
if (vNext[i]->GetNextInMainChain())
|
if (chainActive.Next(vNext[i]))
|
||||||
{
|
{
|
||||||
swap(vNext[0], vNext[i]);
|
swap(vNext[0], vNext[i]);
|
||||||
break;
|
break;
|
||||||
|
@ -3328,7 +3327,7 @@ void static ProcessGetData(CNode* pfrom)
|
||||||
// and we want it right after the last block so they don't
|
// and we want it right after the last block so they don't
|
||||||
// wait for other stuff first.
|
// wait for other stuff first.
|
||||||
vector<CInv> vInv;
|
vector<CInv> vInv;
|
||||||
vInv.push_back(CInv(MSG_BLOCK, hashBestChain));
|
vInv.push_back(CInv(MSG_BLOCK, chainActive.Tip()->GetBlockHash()));
|
||||||
pfrom->PushMessage("inv", vInv);
|
pfrom->PushMessage("inv", vInv);
|
||||||
pfrom->hashContinue = 0;
|
pfrom->hashContinue = 0;
|
||||||
}
|
}
|
||||||
|
@ -3610,7 +3609,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
if (!fImporting && !fReindex)
|
if (!fImporting && !fReindex)
|
||||||
pfrom->AskFor(inv);
|
pfrom->AskFor(inv);
|
||||||
} else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) {
|
} else if (inv.type == MSG_BLOCK && mapOrphanBlocks.count(inv.hash)) {
|
||||||
PushGetBlocks(pfrom, pindexBest, GetOrphanRoot(mapOrphanBlocks[inv.hash]));
|
PushGetBlocks(pfrom, chainActive.Tip(), GetOrphanRoot(mapOrphanBlocks[inv.hash]));
|
||||||
} else if (nInv == nLastBlock) {
|
} else if (nInv == nLastBlock) {
|
||||||
// In case we are on a very long side-chain, it is possible that we already have
|
// In case we are on a very long side-chain, it is possible that we already have
|
||||||
// the last block in an inv bundle sent in response to getblocks. Try to detect
|
// the last block in an inv bundle sent in response to getblocks. Try to detect
|
||||||
|
@ -3658,10 +3657,10 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
|
|
||||||
// Send the rest of the chain
|
// Send the rest of the chain
|
||||||
if (pindex)
|
if (pindex)
|
||||||
pindex = pindex->GetNextInMainChain();
|
pindex = chainActive.Next(pindex);
|
||||||
int nLimit = 500;
|
int nLimit = 500;
|
||||||
LogPrint("net", "getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str(), nLimit);
|
LogPrint("net", "getblocks %d to %s limit %d\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str(), nLimit);
|
||||||
for (; pindex; pindex = pindex->GetNextInMainChain())
|
for (; pindex; pindex = chainActive.Next(pindex))
|
||||||
{
|
{
|
||||||
if (pindex->GetBlockHash() == hashStop)
|
if (pindex->GetBlockHash() == hashStop)
|
||||||
{
|
{
|
||||||
|
@ -3701,14 +3700,14 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv)
|
||||||
// Find the last block the caller has in the main chain
|
// Find the last block the caller has in the main chain
|
||||||
pindex = locator.GetBlockIndex();
|
pindex = locator.GetBlockIndex();
|
||||||
if (pindex)
|
if (pindex)
|
||||||
pindex = pindex->GetNextInMainChain();
|
pindex = chainActive.Next(pindex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
|
// we must use CBlocks, as CBlockHeaders won't include the 0x00 nTx count at the end
|
||||||
vector<CBlock> vHeaders;
|
vector<CBlock> vHeaders;
|
||||||
int nLimit = 2000;
|
int nLimit = 2000;
|
||||||
LogPrint("net", "getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str());
|
LogPrint("net", "getheaders %d to %s\n", (pindex ? pindex->nHeight : -1), hashStop.ToString().c_str());
|
||||||
for (; pindex; pindex = pindex->GetNextInMainChain())
|
for (; pindex; pindex = chainActive.Next(pindex))
|
||||||
{
|
{
|
||||||
vHeaders.push_back(pindex->GetBlockHeader());
|
vHeaders.push_back(pindex->GetBlockHeader());
|
||||||
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
|
if (--nLimit <= 0 || pindex->GetBlockHash() == hashStop)
|
||||||
|
@ -4174,7 +4173,7 @@ bool SendMessages(CNode* pto, bool fSendTrickle)
|
||||||
// Start block sync
|
// Start block sync
|
||||||
if (pto->fStartSync && !fImporting && !fReindex) {
|
if (pto->fStartSync && !fImporting && !fReindex) {
|
||||||
pto->fStartSync = false;
|
pto->fStartSync = false;
|
||||||
PushGetBlocks(pto, pindexBest, uint256(0));
|
PushGetBlocks(pto, chainActive.Tip(), uint256(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Resend wallet transactions that haven't gotten in a block yet
|
// Resend wallet transactions that haven't gotten in a block yet
|
||||||
|
|
83
src/main.h
83
src/main.h
|
@ -74,14 +74,8 @@ extern CScript COINBASE_FLAGS;
|
||||||
|
|
||||||
extern CCriticalSection cs_main;
|
extern CCriticalSection cs_main;
|
||||||
extern std::map<uint256, CBlockIndex*> mapBlockIndex;
|
extern std::map<uint256, CBlockIndex*> mapBlockIndex;
|
||||||
extern std::vector<CBlockIndex*> vBlockIndexByHeight;
|
|
||||||
extern std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid;
|
extern std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexValid;
|
||||||
extern CBlockIndex* pindexGenesisBlock;
|
|
||||||
extern int nBestHeight;
|
|
||||||
extern uint256 nBestChainWork;
|
|
||||||
extern uint256 nBestInvalidWork;
|
extern uint256 nBestInvalidWork;
|
||||||
extern uint256 hashBestChain;
|
|
||||||
extern CBlockIndex* pindexBest;
|
|
||||||
extern unsigned int nTransactionsUpdated;
|
extern unsigned int nTransactionsUpdated;
|
||||||
extern uint64 nLastBlockTx;
|
extern uint64 nLastBlockTx;
|
||||||
extern uint64 nLastBlockSize;
|
extern uint64 nLastBlockSize;
|
||||||
|
@ -153,8 +147,6 @@ void UnloadBlockIndex();
|
||||||
bool VerifyDB(int nCheckLevel, int nCheckDepth);
|
bool VerifyDB(int nCheckLevel, int nCheckDepth);
|
||||||
/** Print the loaded block tree */
|
/** Print the loaded block tree */
|
||||||
void PrintBlockTree();
|
void PrintBlockTree();
|
||||||
/** Find a block by height in the currently-connected chain */
|
|
||||||
CBlockIndex* FindBlockByHeight(int nHeight);
|
|
||||||
/** Process protocol messages received from a given node */
|
/** Process protocol messages received from a given node */
|
||||||
bool ProcessMessages(CNode* pfrom);
|
bool ProcessMessages(CNode* pfrom);
|
||||||
/** Send queued protocol messages to be sent to a give node */
|
/** Send queued protocol messages to be sent to a give node */
|
||||||
|
@ -819,15 +811,6 @@ public:
|
||||||
return (CBigNum(1)<<256) / (bnTarget+1);
|
return (CBigNum(1)<<256) / (bnTarget+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInMainChain() const
|
|
||||||
{
|
|
||||||
return nHeight < (int)vBlockIndexByHeight.size() && vBlockIndexByHeight[nHeight] == this;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBlockIndex *GetNextInMainChain() const {
|
|
||||||
return nHeight+1 >= (int)vBlockIndexByHeight.size() ? NULL : vBlockIndexByHeight[nHeight+1];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CheckIndex() const
|
bool CheckIndex() const
|
||||||
{
|
{
|
||||||
return CheckProofOfWork(GetBlockHash(), nBits);
|
return CheckProofOfWork(GetBlockHash(), nBits);
|
||||||
|
@ -849,17 +832,7 @@ public:
|
||||||
return pbegin[(pend - pbegin)/2];
|
return pbegin[(pend - pbegin)/2];
|
||||||
}
|
}
|
||||||
|
|
||||||
int64 GetMedianTime() const
|
int64 GetMedianTime() const;
|
||||||
{
|
|
||||||
const CBlockIndex* pindex = this;
|
|
||||||
for (int i = 0; i < nMedianTimeSpan/2; i++)
|
|
||||||
{
|
|
||||||
if (!pindex->GetNextInMainChain())
|
|
||||||
return GetBlockTime();
|
|
||||||
pindex = pindex->GetNextInMainChain();
|
|
||||||
}
|
|
||||||
return pindex->GetMedianTimePast();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if there are nRequired or more blocks of minVersion or above
|
* Returns true if there are nRequired or more blocks of minVersion or above
|
||||||
|
@ -870,8 +843,8 @@ public:
|
||||||
|
|
||||||
std::string ToString() const
|
std::string ToString() const
|
||||||
{
|
{
|
||||||
return strprintf("CBlockIndex(pprev=%p, pnext=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
|
return strprintf("CBlockIndex(pprev=%p, nHeight=%d, merkle=%s, hashBlock=%s)",
|
||||||
pprev, GetNextInMainChain(), nHeight,
|
pprev, nHeight,
|
||||||
hashMerkleRoot.ToString().c_str(),
|
hashMerkleRoot.ToString().c_str(),
|
||||||
GetBlockHash().ToString().c_str());
|
GetBlockHash().ToString().c_str());
|
||||||
}
|
}
|
||||||
|
@ -1011,9 +984,59 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** An in-memory indexed chain of blocks. */
|
||||||
|
class CChain {
|
||||||
|
private:
|
||||||
|
std::vector<CBlockIndex*> vChain;
|
||||||
|
|
||||||
|
public:
|
||||||
|
/** Returns the index entry for the genesis block of this chain, or NULL if none. */
|
||||||
|
CBlockIndex *Genesis() const {
|
||||||
|
return vChain.size() > 0 ? vChain[0] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the index entry for the tip of this chain, or NULL if none. */
|
||||||
|
CBlockIndex *Tip() const {
|
||||||
|
return vChain.size() > 0 ? vChain[vChain.size() - 1] : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns the index entry at a particular height in this chain, or NULL if no such height exists. */
|
||||||
|
CBlockIndex *operator[](int nHeight) const {
|
||||||
|
if (nHeight < 0 || nHeight >= (int)vChain.size())
|
||||||
|
return NULL;
|
||||||
|
return vChain[nHeight];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compare two chains efficiently. */
|
||||||
|
friend bool operator==(const CChain &a, const CChain &b) {
|
||||||
|
return a.vChain.size() == b.vChain.size() &&
|
||||||
|
a.vChain[a.vChain.size() - 1] == b.vChain[b.vChain.size() - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Efficiently check whether a block is present in this chain. */
|
||||||
|
bool Contains(const CBlockIndex *pindex) const {
|
||||||
|
return (*this)[pindex->nHeight] == pindex;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Find the successor of a block in this chain, or NULL if the given index is not found or is the tip. */
|
||||||
|
CBlockIndex *Next(const CBlockIndex *pindex) const {
|
||||||
|
if (Contains(pindex))
|
||||||
|
return (*this)[pindex->nHeight + 1];
|
||||||
|
else
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Return the maximal height in the chain. Is equal to chain.Tip() ? chain.Tip()->nHeight : -1. */
|
||||||
|
int Height() const {
|
||||||
|
return vChain.size() - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Set/initialize a chain with a given tip. Returns the forking point. */
|
||||||
|
CBlockIndex *SetTip(CBlockIndex *pindex);
|
||||||
|
};
|
||||||
|
|
||||||
|
/** The currently-connected chain of blocks. */
|
||||||
|
extern CChain chainActive;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -176,7 +176,7 @@ CBlockTemplate* CreateNewBlock(const CScript& scriptPubKeyIn)
|
||||||
int64 nFees = 0;
|
int64 nFees = 0;
|
||||||
{
|
{
|
||||||
LOCK2(cs_main, mempool.cs);
|
LOCK2(cs_main, mempool.cs);
|
||||||
CBlockIndex* pindexPrev = pindexBest;
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||||
CCoinsViewCache view(*pcoinsTip, true);
|
CCoinsViewCache view(*pcoinsTip, true);
|
||||||
|
|
||||||
// Priority order to process transactions
|
// Priority order to process transactions
|
||||||
|
@ -467,7 +467,7 @@ bool CheckWork(CBlock* pblock, CWallet& wallet, CReserveKey& reservekey)
|
||||||
// Found a solution
|
// Found a solution
|
||||||
{
|
{
|
||||||
LOCK(cs_main);
|
LOCK(cs_main);
|
||||||
if (pblock->hashPrevBlock != hashBestChain)
|
if (pblock->hashPrevBlock != chainActive.Tip()->GetBlockHash())
|
||||||
return error("BitcoinMiner : generated block is stale");
|
return error("BitcoinMiner : generated block is stale");
|
||||||
|
|
||||||
// Remove key from key pool
|
// Remove key from key pool
|
||||||
|
@ -510,7 +510,7 @@ void static BitcoinMiner(CWallet *pwallet)
|
||||||
// Create new block
|
// Create new block
|
||||||
//
|
//
|
||||||
unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
|
unsigned int nTransactionsUpdatedLast = nTransactionsUpdated;
|
||||||
CBlockIndex* pindexPrev = pindexBest;
|
CBlockIndex* pindexPrev = chainActive.Tip();
|
||||||
|
|
||||||
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
|
auto_ptr<CBlockTemplate> pblocktemplate(CreateNewBlockWithKey(reservekey));
|
||||||
if (!pblocktemplate.get())
|
if (!pblocktemplate.get())
|
||||||
|
@ -613,7 +613,7 @@ void static BitcoinMiner(CWallet *pwallet)
|
||||||
break;
|
break;
|
||||||
if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
|
if (nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60)
|
||||||
break;
|
break;
|
||||||
if (pindexPrev != pindexBest)
|
if (pindexPrev != chainActive.Tip())
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Update nTime every few seconds
|
// Update nTime every few seconds
|
||||||
|
|
|
@ -540,6 +540,8 @@ void CNode::Cleanup()
|
||||||
|
|
||||||
void CNode::PushVersion()
|
void CNode::PushVersion()
|
||||||
{
|
{
|
||||||
|
int nBestHeight = g_signals.GetHeight().get_value_or(0);
|
||||||
|
|
||||||
/// when NTP implemented, change to just nTime = GetAdjustedTime()
|
/// when NTP implemented, change to just nTime = GetAdjustedTime()
|
||||||
int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
|
int64 nTime = (fInbound ? GetAdjustedTime() : GetTime());
|
||||||
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
|
CAddress addrYou = (addr.IsRoutable() && !IsProxy(addr) ? addr : CAddress(CService("0.0.0.0",0)));
|
||||||
|
@ -1482,6 +1484,8 @@ void static StartSync(const vector<CNode*> &vNodes) {
|
||||||
CNode *pnodeNewSync = NULL;
|
CNode *pnodeNewSync = NULL;
|
||||||
double dBestScore = 0;
|
double dBestScore = 0;
|
||||||
|
|
||||||
|
int nBestHeight = g_signals.GetHeight().get_value_or(0);
|
||||||
|
|
||||||
// Iterate over all nodes
|
// Iterate over all nodes
|
||||||
BOOST_FOREACH(CNode* pnode, vNodes) {
|
BOOST_FOREACH(CNode* pnode, vNodes) {
|
||||||
// check preconditions for allowing a sync
|
// check preconditions for allowing a sync
|
||||||
|
|
|
@ -28,7 +28,6 @@ static const unsigned int MAX_INV_SZ = 50000;
|
||||||
|
|
||||||
class CNode;
|
class CNode;
|
||||||
class CBlockIndex;
|
class CBlockIndex;
|
||||||
extern int nBestHeight;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,6 +51,7 @@ void SocketSendData(CNode *pnode);
|
||||||
// Signals for message handling
|
// Signals for message handling
|
||||||
struct CNodeSignals
|
struct CNodeSignals
|
||||||
{
|
{
|
||||||
|
boost::signals2::signal<int ()> GetHeight;
|
||||||
boost::signals2::signal<bool (CNode*)> ProcessMessages;
|
boost::signals2::signal<bool (CNode*)> ProcessMessages;
|
||||||
boost::signals2::signal<bool (CNode*, bool)> SendMessages;
|
boost::signals2::signal<bool (CNode*, bool)> SendMessages;
|
||||||
};
|
};
|
||||||
|
|
|
@ -42,7 +42,7 @@ int ClientModel::getNumConnections() const
|
||||||
|
|
||||||
int ClientModel::getNumBlocks() const
|
int ClientModel::getNumBlocks() const
|
||||||
{
|
{
|
||||||
return nBestHeight;
|
return chainActive.Height();
|
||||||
}
|
}
|
||||||
|
|
||||||
int ClientModel::getNumBlocksAtStartup()
|
int ClientModel::getNumBlocksAtStartup()
|
||||||
|
@ -53,8 +53,8 @@ int ClientModel::getNumBlocksAtStartup()
|
||||||
|
|
||||||
QDateTime ClientModel::getLastBlockDate() const
|
QDateTime ClientModel::getLastBlockDate() const
|
||||||
{
|
{
|
||||||
if (pindexBest)
|
if (chainActive.Tip())
|
||||||
return QDateTime::fromTime_t(pindexBest->GetBlockTime());
|
return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime());
|
||||||
else if(!isTestNet())
|
else if(!isTestNet())
|
||||||
return QDateTime::fromTime_t(1231006505); // Genesis block's time
|
return QDateTime::fromTime_t(1231006505); // Genesis block's time
|
||||||
else
|
else
|
||||||
|
@ -63,7 +63,7 @@ QDateTime ClientModel::getLastBlockDate() const
|
||||||
|
|
||||||
double ClientModel::getVerificationProgress() const
|
double ClientModel::getVerificationProgress() const
|
||||||
{
|
{
|
||||||
return Checkpoints::GuessVerificationProgress(pindexBest);
|
return Checkpoints::GuessVerificationProgress(chainActive.Tip());
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClientModel::updateTimer()
|
void ClientModel::updateTimer()
|
||||||
|
|
|
@ -17,7 +17,7 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
|
||||||
if (!IsFinalTx(wtx))
|
if (!IsFinalTx(wtx))
|
||||||
{
|
{
|
||||||
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
|
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
|
||||||
return tr("Open for %n more block(s)", "", wtx.nLockTime - nBestHeight + 1);
|
return tr("Open for %n more block(s)", "", wtx.nLockTime - chainActive.Height() + 1);
|
||||||
else
|
else
|
||||||
return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
|
return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
|
||||||
}
|
}
|
||||||
|
|
|
@ -160,14 +160,14 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
|
||||||
idx);
|
idx);
|
||||||
status.confirmed = wtx.IsConfirmed();
|
status.confirmed = wtx.IsConfirmed();
|
||||||
status.depth = wtx.GetDepthInMainChain();
|
status.depth = wtx.GetDepthInMainChain();
|
||||||
status.cur_num_blocks = nBestHeight;
|
status.cur_num_blocks = chainActive.Height();
|
||||||
|
|
||||||
if (!IsFinalTx(wtx))
|
if (!IsFinalTx(wtx))
|
||||||
{
|
{
|
||||||
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
|
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
|
||||||
{
|
{
|
||||||
status.status = TransactionStatus::OpenUntilBlock;
|
status.status = TransactionStatus::OpenUntilBlock;
|
||||||
status.open_for = wtx.nLockTime - nBestHeight + 1;
|
status.open_for = wtx.nLockTime - chainActive.Height() + 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -221,7 +221,7 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
|
||||||
|
|
||||||
bool TransactionRecord::statusUpdateNeeded()
|
bool TransactionRecord::statusUpdateNeeded()
|
||||||
{
|
{
|
||||||
return status.cur_num_blocks != nBestHeight;
|
return status.cur_num_blocks != chainActive.Height();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString TransactionRecord::getTxID() const
|
QString TransactionRecord::getTxID() const
|
||||||
|
|
|
@ -250,9 +250,9 @@ void TransactionTableModel::updateTransaction(const QString &hash, int status)
|
||||||
|
|
||||||
void TransactionTableModel::updateConfirmations()
|
void TransactionTableModel::updateConfirmations()
|
||||||
{
|
{
|
||||||
if(nBestHeight != cachedNumBlocks)
|
if(chainActive.Height() != cachedNumBlocks)
|
||||||
{
|
{
|
||||||
cachedNumBlocks = nBestHeight;
|
cachedNumBlocks = chainActive.Height();
|
||||||
// Blocks came in since last poll.
|
// Blocks came in since last poll.
|
||||||
// Invalidate status (number of confirmations) and (possibly) description
|
// Invalidate status (number of confirmations) and (possibly) description
|
||||||
// for all rows. Qt is smart enough to only actually request the data for the
|
// for all rows. Qt is smart enough to only actually request the data for the
|
||||||
|
|
|
@ -73,10 +73,10 @@ void WalletModel::updateStatus()
|
||||||
|
|
||||||
void WalletModel::pollBalanceChanged()
|
void WalletModel::pollBalanceChanged()
|
||||||
{
|
{
|
||||||
if(nBestHeight != cachedNumBlocks)
|
if(chainActive.Height() != cachedNumBlocks)
|
||||||
{
|
{
|
||||||
// Balance and number of transactions might have changed
|
// Balance and number of transactions might have changed
|
||||||
cachedNumBlocks = nBestHeight;
|
cachedNumBlocks = chainActive.Height();
|
||||||
checkBalanceChanged();
|
checkBalanceChanged();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,10 @@ double GetDifficulty(const CBlockIndex* blockindex)
|
||||||
// minimum difficulty = 1.0.
|
// minimum difficulty = 1.0.
|
||||||
if (blockindex == NULL)
|
if (blockindex == NULL)
|
||||||
{
|
{
|
||||||
if (pindexBest == NULL)
|
if (chainActive.Tip() == NULL)
|
||||||
return 1.0;
|
return 1.0;
|
||||||
else
|
else
|
||||||
blockindex = pindexBest;
|
blockindex = chainActive.Tip();
|
||||||
}
|
}
|
||||||
|
|
||||||
int nShift = (blockindex->nBits >> 24) & 0xff;
|
int nShift = (blockindex->nBits >> 24) & 0xff;
|
||||||
|
@ -66,7 +66,7 @@ Object blockToJSON(const CBlock& block, const CBlockIndex* blockindex)
|
||||||
|
|
||||||
if (blockindex->pprev)
|
if (blockindex->pprev)
|
||||||
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
|
result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));
|
||||||
CBlockIndex *pnext = blockindex->GetNextInMainChain();
|
CBlockIndex *pnext = chainActive.Next(blockindex);
|
||||||
if (pnext)
|
if (pnext)
|
||||||
result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
|
result.push_back(Pair("nextblockhash", pnext->GetBlockHash().GetHex()));
|
||||||
return result;
|
return result;
|
||||||
|
@ -80,7 +80,7 @@ Value getblockcount(const Array& params, bool fHelp)
|
||||||
"getblockcount\n"
|
"getblockcount\n"
|
||||||
"Returns the number of blocks in the longest block chain.");
|
"Returns the number of blocks in the longest block chain.");
|
||||||
|
|
||||||
return nBestHeight;
|
return chainActive.Height();
|
||||||
}
|
}
|
||||||
|
|
||||||
Value getbestblockhash(const Array& params, bool fHelp)
|
Value getbestblockhash(const Array& params, bool fHelp)
|
||||||
|
@ -90,7 +90,7 @@ Value getbestblockhash(const Array& params, bool fHelp)
|
||||||
"getbestblockhash\n"
|
"getbestblockhash\n"
|
||||||
"Returns the hash of the best (tip) block in the longest block chain.");
|
"Returns the hash of the best (tip) block in the longest block chain.");
|
||||||
|
|
||||||
return hashBestChain.GetHex();
|
return chainActive.Tip()->GetBlockHash().GetHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
Value getdifficulty(const Array& params, bool fHelp)
|
Value getdifficulty(const Array& params, bool fHelp)
|
||||||
|
@ -145,11 +145,11 @@ Value getblockhash(const Array& params, bool fHelp)
|
||||||
"Returns hash of block in best-block-chain at <index>.");
|
"Returns hash of block in best-block-chain at <index>.");
|
||||||
|
|
||||||
int nHeight = params[0].get_int();
|
int nHeight = params[0].get_int();
|
||||||
if (nHeight < 0 || nHeight > nBestHeight)
|
if (nHeight < 0 || nHeight > chainActive.Height())
|
||||||
throw runtime_error("Block number out of range.");
|
throw runtime_error("Block number out of range.");
|
||||||
|
|
||||||
CBlockIndex* pblockindex = FindBlockByHeight(nHeight);
|
CBlockIndex* pblockindex = chainActive[nHeight];
|
||||||
return pblockindex->phashBlock->GetHex();
|
return pblockindex->GetBlockHash().GetHex();
|
||||||
}
|
}
|
||||||
|
|
||||||
Value getblock(const Array& params, bool fHelp)
|
Value getblock(const Array& params, bool fHelp)
|
||||||
|
|
|
@ -102,7 +102,7 @@ Value importprivkey(const Array& params, bool fHelp)
|
||||||
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
|
throw JSONRPCError(RPC_WALLET_ERROR, "Error adding key to wallet");
|
||||||
|
|
||||||
if (fRescan) {
|
if (fRescan) {
|
||||||
pwalletMain->ScanForWalletTransactions(pindexGenesisBlock, true);
|
pwalletMain->ScanForWalletTransactions(chainActive.Genesis(), true);
|
||||||
pwalletMain->ReacceptWalletTransactions();
|
pwalletMain->ReacceptWalletTransactions();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -124,7 +124,7 @@ Value importwallet(const Array& params, bool fHelp)
|
||||||
if (!file.is_open())
|
if (!file.is_open())
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file");
|
||||||
|
|
||||||
int64 nTimeBegin = pindexBest->nTime;
|
int64 nTimeBegin = chainActive.Tip()->nTime;
|
||||||
|
|
||||||
bool fGood = true;
|
bool fGood = true;
|
||||||
|
|
||||||
|
@ -175,11 +175,11 @@ Value importwallet(const Array& params, bool fHelp)
|
||||||
}
|
}
|
||||||
file.close();
|
file.close();
|
||||||
|
|
||||||
CBlockIndex *pindex = pindexBest;
|
CBlockIndex *pindex = chainActive.Tip();
|
||||||
while (pindex && pindex->pprev && pindex->nTime > nTimeBegin - 7200)
|
while (pindex && pindex->pprev && pindex->nTime > nTimeBegin - 7200)
|
||||||
pindex = pindex->pprev;
|
pindex = pindex->pprev;
|
||||||
|
|
||||||
LogPrintf("Rescanning last %i blocks\n", pindexBest->nHeight - pindex->nHeight + 1);
|
LogPrintf("Rescanning last %i blocks\n", chainActive.Height() - pindex->nHeight + 1);
|
||||||
pwalletMain->ScanForWalletTransactions(pindex);
|
pwalletMain->ScanForWalletTransactions(pindex);
|
||||||
pwalletMain->ReacceptWalletTransactions();
|
pwalletMain->ReacceptWalletTransactions();
|
||||||
pwalletMain->MarkDirty();
|
pwalletMain->MarkDirty();
|
||||||
|
@ -243,8 +243,8 @@ Value dumpwallet(const Array& params, bool fHelp)
|
||||||
// produce output
|
// produce output
|
||||||
file << strprintf("# Wallet dump created by Bitcoin %s (%s)\n", CLIENT_BUILD.c_str(), CLIENT_DATE.c_str());
|
file << strprintf("# Wallet dump created by Bitcoin %s (%s)\n", CLIENT_BUILD.c_str(), CLIENT_DATE.c_str());
|
||||||
file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()).c_str());
|
file << strprintf("# * Created on %s\n", EncodeDumpTime(GetTime()).c_str());
|
||||||
file << strprintf("# * Best block at time of backup was %i (%s),\n", nBestHeight, hashBestChain.ToString().c_str());
|
file << strprintf("# * Best block at time of backup was %i (%s),\n", chainActive.Height(), chainActive.Tip()->GetBlockHash().ToString().c_str());
|
||||||
file << strprintf("# mined on %s\n", EncodeDumpTime(pindexBest->nTime).c_str());
|
file << strprintf("# mined on %s\n", EncodeDumpTime(chainActive.Tip()->nTime).c_str());
|
||||||
file << "\n";
|
file << "\n";
|
||||||
for (std::vector<std::pair<int64, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
|
for (std::vector<std::pair<int64, CKeyID> >::const_iterator it = vKeyBirth.begin(); it != vKeyBirth.end(); it++) {
|
||||||
const CKeyID &keyid = it->second;
|
const CKeyID &keyid = it->second;
|
||||||
|
|
|
@ -37,10 +37,7 @@ void ShutdownRPCMining()
|
||||||
// or from the last difficulty change if 'lookup' is nonpositive.
|
// or from the last difficulty change if 'lookup' is nonpositive.
|
||||||
// If 'height' is nonnegative, compute the estimate at the time when a given block was found.
|
// If 'height' is nonnegative, compute the estimate at the time when a given block was found.
|
||||||
Value GetNetworkHashPS(int lookup, int height) {
|
Value GetNetworkHashPS(int lookup, int height) {
|
||||||
CBlockIndex *pb = pindexBest;
|
CBlockIndex *pb = chainActive[height];
|
||||||
|
|
||||||
if (height >= 0 && height < nBestHeight)
|
|
||||||
pb = FindBlockByHeight(height);
|
|
||||||
|
|
||||||
if (pb == NULL || !pb->nHeight)
|
if (pb == NULL || !pb->nHeight)
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -148,7 +145,7 @@ Value getmininginfo(const Array& params, bool fHelp)
|
||||||
"Returns an object containing mining-related information.");
|
"Returns an object containing mining-related information.");
|
||||||
|
|
||||||
Object obj;
|
Object obj;
|
||||||
obj.push_back(Pair("blocks", (int)nBestHeight));
|
obj.push_back(Pair("blocks", (int)chainActive.Height()));
|
||||||
obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
|
obj.push_back(Pair("currentblocksize", (uint64_t)nLastBlockSize));
|
||||||
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
|
obj.push_back(Pair("currentblocktx", (uint64_t)nLastBlockTx));
|
||||||
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
obj.push_back(Pair("difficulty", (double)GetDifficulty()));
|
||||||
|
@ -192,10 +189,10 @@ Value getwork(const Array& params, bool fHelp)
|
||||||
static CBlockIndex* pindexPrev;
|
static CBlockIndex* pindexPrev;
|
||||||
static int64 nStart;
|
static int64 nStart;
|
||||||
static CBlockTemplate* pblocktemplate;
|
static CBlockTemplate* pblocktemplate;
|
||||||
if (pindexPrev != pindexBest ||
|
if (pindexPrev != chainActive.Tip() ||
|
||||||
(nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
|
(nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 60))
|
||||||
{
|
{
|
||||||
if (pindexPrev != pindexBest)
|
if (pindexPrev != chainActive.Tip())
|
||||||
{
|
{
|
||||||
// Deallocate old blocks since they're obsolete now
|
// Deallocate old blocks since they're obsolete now
|
||||||
mapNewBlock.clear();
|
mapNewBlock.clear();
|
||||||
|
@ -209,7 +206,7 @@ Value getwork(const Array& params, bool fHelp)
|
||||||
|
|
||||||
// Store the pindexBest used before CreateNewBlock, to avoid races
|
// Store the pindexBest used before CreateNewBlock, to avoid races
|
||||||
nTransactionsUpdatedLast = nTransactionsUpdated;
|
nTransactionsUpdatedLast = nTransactionsUpdated;
|
||||||
CBlockIndex* pindexPrevNew = pindexBest;
|
CBlockIndex* pindexPrevNew = chainActive.Tip();
|
||||||
nStart = GetTime();
|
nStart = GetTime();
|
||||||
|
|
||||||
// Create new block
|
// Create new block
|
||||||
|
@ -328,7 +325,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
|
||||||
static CBlockIndex* pindexPrev;
|
static CBlockIndex* pindexPrev;
|
||||||
static int64 nStart;
|
static int64 nStart;
|
||||||
static CBlockTemplate* pblocktemplate;
|
static CBlockTemplate* pblocktemplate;
|
||||||
if (pindexPrev != pindexBest ||
|
if (pindexPrev != chainActive.Tip() ||
|
||||||
(nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
|
(nTransactionsUpdated != nTransactionsUpdatedLast && GetTime() - nStart > 5))
|
||||||
{
|
{
|
||||||
// Clear pindexPrev so future calls make a new block, despite any failures from here on
|
// Clear pindexPrev so future calls make a new block, despite any failures from here on
|
||||||
|
@ -336,7 +333,7 @@ Value getblocktemplate(const Array& params, bool fHelp)
|
||||||
|
|
||||||
// Store the pindexBest used before CreateNewBlock, to avoid races
|
// Store the pindexBest used before CreateNewBlock, to avoid races
|
||||||
nTransactionsUpdatedLast = nTransactionsUpdated;
|
nTransactionsUpdatedLast = nTransactionsUpdated;
|
||||||
CBlockIndex* pindexPrevNew = pindexBest;
|
CBlockIndex* pindexPrevNew = chainActive.Tip();
|
||||||
nStart = GetTime();
|
nStart = GetTime();
|
||||||
|
|
||||||
// Create new block
|
// Create new block
|
||||||
|
|
|
@ -87,9 +87,9 @@ void TxToJSON(const CTransaction& tx, const uint256 hashBlock, Object& entry)
|
||||||
if (mi != mapBlockIndex.end() && (*mi).second)
|
if (mi != mapBlockIndex.end() && (*mi).second)
|
||||||
{
|
{
|
||||||
CBlockIndex* pindex = (*mi).second;
|
CBlockIndex* pindex = (*mi).second;
|
||||||
if (pindex->IsInMainChain())
|
if (chainActive.Contains(pindex))
|
||||||
{
|
{
|
||||||
entry.push_back(Pair("confirmations", 1 + nBestHeight - pindex->nHeight));
|
entry.push_back(Pair("confirmations", 1 + chainActive.Height() - pindex->nHeight));
|
||||||
entry.push_back(Pair("time", (boost::int64_t)pindex->nTime));
|
entry.push_back(Pair("time", (boost::int64_t)pindex->nTime));
|
||||||
entry.push_back(Pair("blocktime", (boost::int64_t)pindex->nTime));
|
entry.push_back(Pair("blocktime", (boost::int64_t)pindex->nTime));
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ Value getinfo(const Array& params, bool fHelp)
|
||||||
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
|
obj.push_back(Pair("walletversion", pwalletMain->GetVersion()));
|
||||||
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
|
obj.push_back(Pair("balance", ValueFromAmount(pwalletMain->GetBalance())));
|
||||||
}
|
}
|
||||||
obj.push_back(Pair("blocks", (int)nBestHeight));
|
obj.push_back(Pair("blocks", (int)chainActive.Height()));
|
||||||
obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset()));
|
obj.push_back(Pair("timeoffset", (boost::int64_t)GetTimeOffset()));
|
||||||
obj.push_back(Pair("connections", (int)vNodes.size()));
|
obj.push_back(Pair("connections", (int)vNodes.size()));
|
||||||
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
|
obj.push_back(Pair("proxy", (proxy.first.IsValid() ? proxy.first.ToStringIPPort() : string())));
|
||||||
|
@ -1180,7 +1180,7 @@ Value listsinceblock(const Array& params, bool fHelp)
|
||||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
|
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter");
|
||||||
}
|
}
|
||||||
|
|
||||||
int depth = pindex ? (1 + nBestHeight - pindex->nHeight) : -1;
|
int depth = pindex ? (1 + chainActive.Height() - pindex->nHeight) : -1;
|
||||||
|
|
||||||
Array transactions;
|
Array transactions;
|
||||||
|
|
||||||
|
@ -1192,23 +1192,8 @@ Value listsinceblock(const Array& params, bool fHelp)
|
||||||
ListTransactions(tx, "*", 0, true, transactions);
|
ListTransactions(tx, "*", 0, true, transactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint256 lastblock;
|
CBlockIndex *pblockLast = chainActive[chainActive.Height() + 1 - target_confirms];
|
||||||
|
uint256 lastblock = pblockLast ? pblockLast->GetBlockHash() : 0;
|
||||||
if (target_confirms == 1)
|
|
||||||
{
|
|
||||||
lastblock = hashBestChain;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int target_height = pindexBest->nHeight + 1 - target_confirms;
|
|
||||||
|
|
||||||
CBlockIndex *block;
|
|
||||||
for (block = pindexBest;
|
|
||||||
block && block->nHeight > target_height;
|
|
||||||
block = block->pprev) { }
|
|
||||||
|
|
||||||
lastblock = block ? block->GetBlockHash() : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
Object ret;
|
Object ret;
|
||||||
ret.push_back(Pair("transactions", transactions));
|
ret.push_back(Pair("transactions", transactions));
|
||||||
|
|
|
@ -65,10 +65,10 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||||
{
|
{
|
||||||
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
CBlock *pblock = &pblocktemplate->block; // pointer for convenience
|
||||||
pblock->nVersion = 1;
|
pblock->nVersion = 1;
|
||||||
pblock->nTime = pindexBest->GetMedianTimePast()+1;
|
pblock->nTime = chainActive.Tip()->GetMedianTimePast()+1;
|
||||||
pblock->vtx[0].vin[0].scriptSig = CScript();
|
pblock->vtx[0].vin[0].scriptSig = CScript();
|
||||||
pblock->vtx[0].vin[0].scriptSig.push_back(blockinfo[i].extranonce);
|
pblock->vtx[0].vin[0].scriptSig.push_back(blockinfo[i].extranonce);
|
||||||
pblock->vtx[0].vin[0].scriptSig.push_back(pindexBest->nHeight);
|
pblock->vtx[0].vin[0].scriptSig.push_back(chainActive.Height());
|
||||||
pblock->vtx[0].vout[0].scriptPubKey = CScript();
|
pblock->vtx[0].vout[0].scriptPubKey = CScript();
|
||||||
if (txFirst.size() < 2)
|
if (txFirst.size() < 2)
|
||||||
txFirst.push_back(new CTransaction(pblock->vtx[0]));
|
txFirst.push_back(new CTransaction(pblock->vtx[0]));
|
||||||
|
@ -193,14 +193,14 @@ BOOST_AUTO_TEST_CASE(CreateNewBlock_validity)
|
||||||
mempool.clear();
|
mempool.clear();
|
||||||
|
|
||||||
// subsidy changing
|
// subsidy changing
|
||||||
int nHeight = pindexBest->nHeight;
|
int nHeight = chainActive.Height();
|
||||||
pindexBest->nHeight = 209999;
|
chainActive.Tip()->nHeight = 209999;
|
||||||
BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
|
BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
|
||||||
delete pblocktemplate;
|
delete pblocktemplate;
|
||||||
pindexBest->nHeight = 210000;
|
chainActive.Tip()->nHeight = 210000;
|
||||||
BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
|
BOOST_CHECK(pblocktemplate = CreateNewBlockWithKey(reservekey));
|
||||||
delete pblocktemplate;
|
delete pblocktemplate;
|
||||||
pindexBest->nHeight = nHeight;
|
chainActive.Tip()->nHeight = nHeight;
|
||||||
|
|
||||||
BOOST_FOREACH(CTransaction *tx, txFirst)
|
BOOST_FOREACH(CTransaction *tx, txFirst)
|
||||||
delete tx;
|
delete tx;
|
||||||
|
|
|
@ -223,10 +223,6 @@ bool CBlockTreeDB::LoadBlockIndexGuts()
|
||||||
pindexNew->nStatus = diskindex.nStatus;
|
pindexNew->nStatus = diskindex.nStatus;
|
||||||
pindexNew->nTx = diskindex.nTx;
|
pindexNew->nTx = diskindex.nTx;
|
||||||
|
|
||||||
// Watch for genesis block
|
|
||||||
if (pindexGenesisBlock == NULL && diskindex.GetBlockHash() == Params().HashGenesisBlock())
|
|
||||||
pindexGenesisBlock = pindexNew;
|
|
||||||
|
|
||||||
if (!pindexNew->CheckIndex())
|
if (!pindexNew->CheckIndex())
|
||||||
return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str());
|
return error("LoadBlockIndex() : CheckIndex failed: %s", pindexNew->ToString().c_str());
|
||||||
|
|
||||||
|
|
|
@ -799,7 +799,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
|
||||||
// no need to read and scan block, if block was created before
|
// no need to read and scan block, if block was created before
|
||||||
// our wallet birthday (as adjusted for block time variability)
|
// our wallet birthday (as adjusted for block time variability)
|
||||||
if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) {
|
if (nTimeFirstKey && (pindex->nTime < (nTimeFirstKey - 7200))) {
|
||||||
pindex = pindex->GetNextInMainChain();
|
pindex = chainActive.Next(pindex);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -810,7 +810,7 @@ int CWallet::ScanForWalletTransactions(CBlockIndex* pindexStart, bool fUpdate)
|
||||||
if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
|
if (AddToWalletIfInvolvingMe(tx.GetHash(), tx, &block, fUpdate))
|
||||||
ret++;
|
ret++;
|
||||||
}
|
}
|
||||||
pindex = pindex->GetNextInMainChain();
|
pindex = chainActive.Next(pindex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -864,7 +864,7 @@ void CWallet::ReacceptWalletTransactions()
|
||||||
if (fMissing)
|
if (fMissing)
|
||||||
{
|
{
|
||||||
// TODO: optimize this to scan just part of the block chain?
|
// TODO: optimize this to scan just part of the block chain?
|
||||||
if (ScanForWalletTransactions(pindexGenesisBlock))
|
if (ScanForWalletTransactions(chainActive.Genesis()))
|
||||||
fRepeat = true; // Found missing transactions: re-do re-accept.
|
fRepeat = true; // Found missing transactions: re-do re-accept.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1933,7 +1933,7 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
|
||||||
mapKeyBirth[it->first] = it->second.nCreateTime;
|
mapKeyBirth[it->first] = it->second.nCreateTime;
|
||||||
|
|
||||||
// map in which we'll infer heights of other keys
|
// map in which we'll infer heights of other keys
|
||||||
CBlockIndex *pindexMax = FindBlockByHeight(std::max(0, nBestHeight - 144)); // the tip can be reorganised; use a 144-block safety margin
|
CBlockIndex *pindexMax = chainActive[std::max(0, chainActive.Height() - 144)]; // the tip can be reorganised; use a 144-block safety margin
|
||||||
std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
|
std::map<CKeyID, CBlockIndex*> mapKeyFirstBlock;
|
||||||
std::set<CKeyID> setKeys;
|
std::set<CKeyID> setKeys;
|
||||||
GetKeys(setKeys);
|
GetKeys(setKeys);
|
||||||
|
@ -1953,7 +1953,7 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64> &mapKeyBirth) const {
|
||||||
// iterate over all wallet transactions...
|
// iterate over all wallet transactions...
|
||||||
const CWalletTx &wtx = (*it).second;
|
const CWalletTx &wtx = (*it).second;
|
||||||
std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
|
std::map<uint256, CBlockIndex*>::const_iterator blit = mapBlockIndex.find(wtx.hashBlock);
|
||||||
if (blit != mapBlockIndex.end() && blit->second->IsInMainChain()) {
|
if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
|
||||||
// ... which are already in a block
|
// ... which are already in a block
|
||||||
int nHeight = blit->second->nHeight;
|
int nHeight = blit->second->nHeight;
|
||||||
BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
|
BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
|
||||||
|
|
Loading…
Reference in a new issue