|
|
@ -113,6 +113,39 @@ private: |
|
|
|
* missing the data for the block. |
|
|
|
* missing the data for the block. |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates; |
|
|
|
std::set<CBlockIndex*, CBlockIndexWorkComparator> setBlockIndexCandidates; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Every received block is assigned a unique and increasing identifier, so we |
|
|
|
|
|
|
|
* know which one to give priority in case of a fork. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
CCriticalSection cs_nBlockSequenceId; |
|
|
|
|
|
|
|
/** Blocks loaded from disk are assigned id 0, so start the counter at 1. */ |
|
|
|
|
|
|
|
int32_t nBlockSequenceId = 1; |
|
|
|
|
|
|
|
/** Decreasing counter (used by subsequent preciousblock calls). */ |
|
|
|
|
|
|
|
int32_t nBlockReverseSequenceId = -1; |
|
|
|
|
|
|
|
/** chainwork for the last block that preciousblock has been applied to. */ |
|
|
|
|
|
|
|
arith_uint256 nLastPreciousChainwork = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** In order to efficiently track invalidity of headers, we keep the set of
|
|
|
|
|
|
|
|
* blocks which we tried to connect and found to be invalid here (ie which |
|
|
|
|
|
|
|
* were set to BLOCK_FAILED_VALID since the last restart). We can then |
|
|
|
|
|
|
|
* walk this set and check if a new header is a descendant of something in |
|
|
|
|
|
|
|
* this set, preventing us from having to walk mapBlockIndex when we try |
|
|
|
|
|
|
|
* to connect a bad block and fail. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* While this is more complicated than marking everything which descends |
|
|
|
|
|
|
|
* from an invalid block as invalid at the time we discover it to be |
|
|
|
|
|
|
|
* invalid, doing so would require walking all of mapBlockIndex to find all |
|
|
|
|
|
|
|
* descendants. Since this case should be very rare, keeping track of all |
|
|
|
|
|
|
|
* BLOCK_FAILED_VALID blocks in a set should be just fine and work just as |
|
|
|
|
|
|
|
* well. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Because we already walk mapBlockIndex in height-order at startup, we go |
|
|
|
|
|
|
|
* ahead and mark descendants of invalid blocks as FAILED_CHILD at that time, |
|
|
|
|
|
|
|
* instead of putting things in this set. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
std::set<CBlockIndex*> g_failed_blocks; |
|
|
|
|
|
|
|
|
|
|
|
public: |
|
|
|
public: |
|
|
|
CChain chainActive; |
|
|
|
CChain chainActive; |
|
|
|
BlockMap mapBlockIndex; |
|
|
|
BlockMap mapBlockIndex; |
|
|
@ -220,38 +253,6 @@ namespace { |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
bool fCheckForPruning = false; |
|
|
|
bool fCheckForPruning = false; |
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
|
|
* Every received block is assigned a unique and increasing identifier, so we |
|
|
|
|
|
|
|
* know which one to give priority in case of a fork. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
CCriticalSection cs_nBlockSequenceId; |
|
|
|
|
|
|
|
/** Blocks loaded from disk are assigned id 0, so start the counter at 1. */ |
|
|
|
|
|
|
|
int32_t nBlockSequenceId = 1; |
|
|
|
|
|
|
|
/** Decreasing counter (used by subsequent preciousblock calls). */ |
|
|
|
|
|
|
|
int32_t nBlockReverseSequenceId = -1; |
|
|
|
|
|
|
|
/** chainwork for the last block that preciousblock has been applied to. */ |
|
|
|
|
|
|
|
arith_uint256 nLastPreciousChainwork = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** In order to efficiently track invalidity of headers, we keep the set of
|
|
|
|
|
|
|
|
* blocks which we tried to connect and found to be invalid here (ie which |
|
|
|
|
|
|
|
* were set to BLOCK_FAILED_VALID since the last restart). We can then |
|
|
|
|
|
|
|
* walk this set and check if a new header is a descendant of something in |
|
|
|
|
|
|
|
* this set, preventing us from having to walk mapBlockIndex when we try |
|
|
|
|
|
|
|
* to connect a bad block and fail. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* While this is more complicated than marking everything which descends |
|
|
|
|
|
|
|
* from an invalid block as invalid at the time we discover it to be |
|
|
|
|
|
|
|
* invalid, doing so would require walking all of mapBlockIndex to find all |
|
|
|
|
|
|
|
* descendants. Since this case should be very rare, keeping track of all |
|
|
|
|
|
|
|
* BLOCK_FAILED_VALID blocks in a set should be just fine and work just as |
|
|
|
|
|
|
|
* well. |
|
|
|
|
|
|
|
* |
|
|
|
|
|
|
|
* Because we already walk mapBlockIndex in height-order at startup, we go |
|
|
|
|
|
|
|
* ahead and mark descendants of invalid blocks as FAILED_CHILD at that time, |
|
|
|
|
|
|
|
* instead of putting things in this set. |
|
|
|
|
|
|
|
*/ |
|
|
|
|
|
|
|
std::set<CBlockIndex*> g_failed_blocks; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** Dirty block index entries. */ |
|
|
|
/** Dirty block index entries. */ |
|
|
|
std::set<CBlockIndex*> setDirtyBlockIndex; |
|
|
|
std::set<CBlockIndex*> setDirtyBlockIndex; |
|
|
|
|
|
|
|
|
|
|
@ -2129,10 +2130,8 @@ static void DoWarning(const std::string& strWarning) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
/** Update chainActive and related internal data structures. */ |
|
|
|
/** Check warning conditions and do some notifications on new chain tip set. */ |
|
|
|
void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { |
|
|
|
void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainParams) { |
|
|
|
chainActive.SetTip(pindexNew); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// New best block
|
|
|
|
// New best block
|
|
|
|
mempool.AddTransactionsUpdated(1); |
|
|
|
mempool.AddTransactionsUpdated(1); |
|
|
|
|
|
|
|
|
|
|
@ -2142,7 +2141,7 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { |
|
|
|
if (!IsInitialBlockDownload()) |
|
|
|
if (!IsInitialBlockDownload()) |
|
|
|
{ |
|
|
|
{ |
|
|
|
int nUpgraded = 0; |
|
|
|
int nUpgraded = 0; |
|
|
|
const CBlockIndex* pindex = chainActive.Tip(); |
|
|
|
const CBlockIndex* pindex = pindexNew; |
|
|
|
for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) { |
|
|
|
for (int bit = 0; bit < VERSIONBITS_NUM_BITS; bit++) { |
|
|
|
WarningBitsConditionChecker checker(bit); |
|
|
|
WarningBitsConditionChecker checker(bit); |
|
|
|
ThresholdState state = checker.GetStateFor(pindex, chainParams.GetConsensus(), warningcache[bit]); |
|
|
|
ThresholdState state = checker.GetStateFor(pindex, chainParams.GetConsensus(), warningcache[bit]); |
|
|
@ -2173,10 +2172,10 @@ void static UpdateTip(CBlockIndex *pindexNew, const CChainParams& chainParams) { |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)", __func__, |
|
|
|
LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo)", __func__, |
|
|
|
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), chainActive.Tip()->nVersion, |
|
|
|
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion, |
|
|
|
log(chainActive.Tip()->nChainWork.getdouble())/log(2.0), (unsigned long)chainActive.Tip()->nChainTx, |
|
|
|
log(pindexNew->nChainWork.getdouble())/log(2.0), (unsigned long)pindexNew->nChainTx, |
|
|
|
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", chainActive.Tip()->GetBlockTime()), |
|
|
|
DateTimeStrFormat("%Y-%m-%d %H:%M:%S", pindexNew->GetBlockTime()), |
|
|
|
GuessVerificationProgress(chainParams.TxData(), chainActive.Tip()), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); |
|
|
|
GuessVerificationProgress(chainParams.TxData(), pindexNew), pcoinsTip->DynamicMemoryUsage() * (1.0 / (1<<20)), pcoinsTip->GetCacheSize()); |
|
|
|
if (!warningMessages.empty()) |
|
|
|
if (!warningMessages.empty()) |
|
|
|
LogPrintf(" warning='%s'", boost::algorithm::join(warningMessages, ", ")); |
|
|
|
LogPrintf(" warning='%s'", boost::algorithm::join(warningMessages, ", ")); |
|
|
|
LogPrintf("\n"); |
|
|
|
LogPrintf("\n"); |
|
|
@ -2230,7 +2229,8 @@ bool CChainState::DisconnectTip(CValidationState& state, const CChainParams& cha |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Update chainActive and related variables.
|
|
|
|
chainActive.SetTip(pindexDelete->pprev); |
|
|
|
|
|
|
|
|
|
|
|
UpdateTip(pindexDelete->pprev, chainparams); |
|
|
|
UpdateTip(pindexDelete->pprev, chainparams); |
|
|
|
// Let wallets know transactions went from 1-confirmed to
|
|
|
|
// Let wallets know transactions went from 1-confirmed to
|
|
|
|
// 0-confirmed or conflicted:
|
|
|
|
// 0-confirmed or conflicted:
|
|
|
@ -2359,6 +2359,7 @@ bool CChainState::ConnectTip(CValidationState& state, const CChainParams& chainp |
|
|
|
mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight); |
|
|
|
mempool.removeForBlock(blockConnecting.vtx, pindexNew->nHeight); |
|
|
|
disconnectpool.removeForBlock(blockConnecting.vtx); |
|
|
|
disconnectpool.removeForBlock(blockConnecting.vtx); |
|
|
|
// Update chainActive & related variables.
|
|
|
|
// Update chainActive & related variables.
|
|
|
|
|
|
|
|
chainActive.SetTip(pindexNew); |
|
|
|
UpdateTip(pindexNew, chainparams); |
|
|
|
UpdateTip(pindexNew, chainparams); |
|
|
|
|
|
|
|
|
|
|
|
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; |
|
|
|
int64_t nTime6 = GetTimeMicros(); nTimePostConnect += nTime6 - nTime5; nTimeTotal += nTime6 - nTime1; |
|
|
@ -4087,6 +4088,8 @@ bool RewindBlockIndex(const CChainParams& params) { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void CChainState::UnloadBlockIndex() { |
|
|
|
void CChainState::UnloadBlockIndex() { |
|
|
|
|
|
|
|
nBlockSequenceId = 1; |
|
|
|
|
|
|
|
g_failed_blocks.clear(); |
|
|
|
setBlockIndexCandidates.clear(); |
|
|
|
setBlockIndexCandidates.clear(); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -4103,9 +4106,7 @@ void UnloadBlockIndex() |
|
|
|
mapBlocksUnlinked.clear(); |
|
|
|
mapBlocksUnlinked.clear(); |
|
|
|
vinfoBlockFile.clear(); |
|
|
|
vinfoBlockFile.clear(); |
|
|
|
nLastBlockFile = 0; |
|
|
|
nLastBlockFile = 0; |
|
|
|
nBlockSequenceId = 1; |
|
|
|
|
|
|
|
setDirtyBlockIndex.clear(); |
|
|
|
setDirtyBlockIndex.clear(); |
|
|
|
g_failed_blocks.clear(); |
|
|
|
|
|
|
|
setDirtyFileInfo.clear(); |
|
|
|
setDirtyFileInfo.clear(); |
|
|
|
versionbitscache.Clear(); |
|
|
|
versionbitscache.Clear(); |
|
|
|
for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) { |
|
|
|
for (int b = 0; b < VERSIONBITS_NUM_BITS; b++) { |
|
|
@ -4637,7 +4638,7 @@ bool DumpMempool(void) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
//! Guess how far we are in the verification process at the given block index
|
|
|
|
//! Guess how far we are in the verification process at the given block index
|
|
|
|
double GuessVerificationProgress(const ChainTxData& data, CBlockIndex *pindex) { |
|
|
|
double GuessVerificationProgress(const ChainTxData& data, const CBlockIndex *pindex) { |
|
|
|
if (pindex == nullptr) |
|
|
|
if (pindex == nullptr) |
|
|
|
return 0.0; |
|
|
|
return 0.0; |
|
|
|
|
|
|
|
|
|
|
|