|
|
@ -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;
|
|
|
|
|
|
|
|
|
|
|
|