Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 246 Lines • ▼ Show 20 Lines | |||||
* AcceptToMemoryPool. See CTxMemPool::cs comment for details. | * AcceptToMemoryPool. See CTxMemPool::cs comment for details. | ||||
* | * | ||||
* The transaction pool has a separate lock to allow reading from it and the | * The transaction pool has a separate lock to allow reading from it and the | ||||
* chainstate at the same time. | * chainstate at the same time. | ||||
*/ | */ | ||||
RecursiveMutex cs_main; | RecursiveMutex cs_main; | ||||
BlockMap &mapBlockIndex = g_chainstate.mapBlockIndex; | BlockMap &mapBlockIndex = g_chainstate.mapBlockIndex; | ||||
CChain &chainActive = g_chainstate.m_chain; | |||||
CBlockIndex *pindexBestHeader = nullptr; | CBlockIndex *pindexBestHeader = nullptr; | ||||
Mutex g_best_block_mutex; | Mutex g_best_block_mutex; | ||||
std::condition_variable g_best_block_cv; | std::condition_variable g_best_block_cv; | ||||
uint256 g_best_block; | uint256 g_best_block; | ||||
int nScriptCheckThreads = 0; | int nScriptCheckThreads = 0; | ||||
std::atomic_bool fImporting(false); | std::atomic_bool fImporting(false); | ||||
std::atomic_bool fReindex(false); | std::atomic_bool fReindex(false); | ||||
bool fHavePruned = false; | bool fHavePruned = false; | ||||
▲ Show 20 Lines • Show All 99 Lines • ▼ Show 20 Lines | |||||
bool TestLockPointValidity(const LockPoints *lp) { | bool TestLockPointValidity(const LockPoints *lp) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
assert(lp); | assert(lp); | ||||
// If there are relative lock times then the maxInputBlock will be set | // If there are relative lock times then the maxInputBlock will be set | ||||
// If there are no relative lock times, the LockPoints don't depend on the | // If there are no relative lock times, the LockPoints don't depend on the | ||||
// chain | // chain | ||||
if (lp->maxInputBlock) { | if (lp->maxInputBlock) { | ||||
// Check whether chainActive is an extension of the block at which the | // Check whether ::ChainActive() is an extension of the block at which | ||||
// LockPoints calculation was valid. If not LockPoints are no longer | // the LockPoints calculation was valid. If not LockPoints are no longer | ||||
// valid. | // valid. | ||||
if (!chainActive.Contains(lp->maxInputBlock)) { | if (!::ChainActive().Contains(lp->maxInputBlock)) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
// LockPoints still valid | // LockPoints still valid | ||||
return true; | return true; | ||||
} | } | ||||
bool CheckSequenceLocks(const CTxMemPool &pool, const CTransaction &tx, | bool CheckSequenceLocks(const CTxMemPool &pool, const CTransaction &tx, | ||||
int flags, LockPoints *lp, bool useExistingLockPoints) { | int flags, LockPoints *lp, bool useExistingLockPoints) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
AssertLockHeld(pool.cs); | AssertLockHeld(pool.cs); | ||||
CBlockIndex *tip = chainActive.Tip(); | CBlockIndex *tip = ::ChainActive().Tip(); | ||||
assert(tip != nullptr); | assert(tip != nullptr); | ||||
CBlockIndex index; | CBlockIndex index; | ||||
index.pprev = tip; | index.pprev = tip; | ||||
// CheckSequenceLocks() uses chainActive.Height()+1 to evaluate height based | // CheckSequenceLocks() uses ::ChainActive().Height()+1 to evaluate height | ||||
// locks because when SequenceLocks() is called within ConnectBlock(), the | // based locks because when SequenceLocks() is called within ConnectBlock(), | ||||
// height of the block *being* evaluated is what is used. Thus if we want to | // the height of the block *being* evaluated is what is used. Thus if we | ||||
// know if a transaction can be part of the *next* block, we need to use one | // want to know if a transaction can be part of the *next* block, we need to | ||||
// more than chainActive.Height() | // use one more than ::ChainActive().Height() | ||||
index.nHeight = tip->nHeight + 1; | index.nHeight = tip->nHeight + 1; | ||||
std::pair<int, int64_t> lockPair; | std::pair<int, int64_t> lockPair; | ||||
if (useExistingLockPoints) { | if (useExistingLockPoints) { | ||||
assert(lp); | assert(lp); | ||||
lockPair.first = lp->height; | lockPair.first = lp->height; | ||||
lockPair.second = lp->time; | lockPair.second = lp->time; | ||||
} else { | } else { | ||||
// pcoinsTip contains the UTXO set for chainActive.Tip() | // pcoinsTip contains the UTXO set for ::ChainActive().Tip() | ||||
CCoinsViewMemPool viewMemPool(pcoinsTip.get(), pool); | CCoinsViewMemPool viewMemPool(pcoinsTip.get(), pool); | ||||
std::vector<int> prevheights; | std::vector<int> prevheights; | ||||
prevheights.resize(tx.vin.size()); | prevheights.resize(tx.vin.size()); | ||||
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) { | for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) { | ||||
const CTxIn &txin = tx.vin[txinIndex]; | const CTxIn &txin = tx.vin[txinIndex]; | ||||
Coin coin; | Coin coin; | ||||
if (!viewMemPool.GetCoin(txin.prevout, coin)) { | if (!viewMemPool.GetCoin(txin.prevout, coin)) { | ||||
return error("%s: Missing input", __func__); | return error("%s: Missing input", __func__); | ||||
▲ Show 20 Lines • Show All 250 Lines • ▼ Show 20 Lines | for (const CTxIn &txin : tx.vin) { | ||||
Amount nFees = Amount::zero(); | Amount nFees = Amount::zero(); | ||||
if (!Consensus::CheckTxInputs(tx, state, view, GetSpendHeight(view), | if (!Consensus::CheckTxInputs(tx, state, view, GetSpendHeight(view), | ||||
nFees)) { | nFees)) { | ||||
return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, | return error("%s: Consensus::CheckTxInputs: %s, %s", __func__, | ||||
tx.GetId().ToString(), FormatStateMessage(state)); | tx.GetId().ToString(), FormatStateMessage(state)); | ||||
} | } | ||||
const uint32_t nextBlockScriptVerifyFlags = | const uint32_t nextBlockScriptVerifyFlags = | ||||
GetNextBlockScriptFlags(consensusParams, chainActive.Tip()); | GetNextBlockScriptFlags(consensusParams, ::ChainActive().Tip()); | ||||
// Check for non-standard pay-to-script-hash in inputs | // Check for non-standard pay-to-script-hash in inputs | ||||
if (fRequireStandard && | if (fRequireStandard && | ||||
!AreInputsStandard(tx, view, nextBlockScriptVerifyFlags)) { | !AreInputsStandard(tx, view, nextBlockScriptVerifyFlags)) { | ||||
return state.Invalid(false, REJECT_NONSTANDARD, | return state.Invalid(false, REJECT_NONSTANDARD, | ||||
"bad-txns-nonstandard-inputs"); | "bad-txns-nonstandard-inputs"); | ||||
} | } | ||||
Show All 37 Lines | for (const CTxIn &txin : tx.vin) { | ||||
if (nAbsurdFee != Amount::zero() && nFees > nAbsurdFee) { | if (nAbsurdFee != Amount::zero() && nFees > nAbsurdFee) { | ||||
return state.Invalid(false, REJECT_HIGHFEE, "absurdly-high-fee", | return state.Invalid(false, REJECT_HIGHFEE, "absurdly-high-fee", | ||||
strprintf("%d > %d", nFees, nAbsurdFee)); | strprintf("%d > %d", nFees, nAbsurdFee)); | ||||
} | } | ||||
// Validate input scripts against standard script flags. | // Validate input scripts against standard script flags. | ||||
const uint32_t scriptVerifyFlags = | const uint32_t scriptVerifyFlags = | ||||
GetStandardScriptFlags(consensusParams, chainActive.Tip()); | GetStandardScriptFlags(consensusParams, ::ChainActive().Tip()); | ||||
PrecomputedTransactionData txdata(tx); | PrecomputedTransactionData txdata(tx); | ||||
int nSigChecksStandard; | int nSigChecksStandard; | ||||
if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, false, | if (!CheckInputs(tx, state, view, true, scriptVerifyFlags, true, false, | ||||
txdata, nSigChecksStandard)) { | txdata, nSigChecksStandard)) { | ||||
// State filled in by CheckInputs. | // State filled in by CheckInputs. | ||||
return false; | return false; | ||||
} | } | ||||
// After the sigchecks activation we repurpose the 'sigops' tracking in | // After the sigchecks activation we repurpose the 'sigops' tracking in | ||||
// mempool/mining to actually track sigchecks instead. (Proper SigOps | // mempool/mining to actually track sigchecks instead. (Proper SigOps | ||||
// will not need to be counted any more since it's getting deactivated.) | // will not need to be counted any more since it's getting deactivated.) | ||||
auto nSigChecksOrOps = | auto nSigChecksOrOps = | ||||
(nextBlockScriptVerifyFlags & SCRIPT_REPORT_SIGCHECKS) | (nextBlockScriptVerifyFlags & SCRIPT_REPORT_SIGCHECKS) | ||||
? nSigChecksStandard | ? nSigChecksStandard | ||||
: nSigOpsCount; | : nSigOpsCount; | ||||
CTxMemPoolEntry entry(ptx, nFees, nAcceptTime, chainActive.Height(), | CTxMemPoolEntry entry(ptx, nFees, nAcceptTime, ::ChainActive().Height(), | ||||
fSpendsCoinbase, nSigChecksOrOps, lp); | fSpendsCoinbase, nSigChecksOrOps, lp); | ||||
unsigned int nVirtualSize = entry.GetTxVirtualSize(); | unsigned int nVirtualSize = entry.GetTxVirtualSize(); | ||||
Amount mempoolRejectFee = | Amount mempoolRejectFee = | ||||
pool.GetMinFee( | pool.GetMinFee( | ||||
gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * | gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * | ||||
1000000) | 1000000) | ||||
.GetFee(nVirtualSize); | .GetFee(nVirtualSize); | ||||
if (!bypass_limits && mempoolRejectFee > Amount::zero() && | if (!bypass_limits && mempoolRejectFee > Amount::zero() && | ||||
nModifiedFees < mempoolRejectFee) { | nModifiedFees < mempoolRejectFee) { | ||||
return state.DoS( | return state.DoS( | ||||
0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", | 0, false, REJECT_INSUFFICIENTFEE, "mempool min fee not met", | ||||
false, strprintf("%d < %d", nModifiedFees, mempoolRejectFee)); | false, strprintf("%d < %d", nModifiedFees, mempoolRejectFee)); | ||||
} | } | ||||
// Calculate in-mempool ancestors, up to a limit. | // Calculate in-mempool ancestors, up to a limit. | ||||
CTxMemPool::setEntries setAncestors; | CTxMemPool::setEntries setAncestors; | ||||
size_t nLimitAncestors = gArgs.GetArg( | size_t nLimitAncestors = gArgs.GetArg( | ||||
"-limitancestorcount", | "-limitancestorcount", | ||||
GetDefaultAncestorLimit(consensusParams, chainActive.Tip())); | GetDefaultAncestorLimit(consensusParams, ::ChainActive().Tip())); | ||||
size_t nLimitAncestorSize = | size_t nLimitAncestorSize = | ||||
gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT) * | gArgs.GetArg("-limitancestorsize", DEFAULT_ANCESTOR_SIZE_LIMIT) * | ||||
1000; | 1000; | ||||
size_t nLimitDescendants = gArgs.GetArg( | size_t nLimitDescendants = gArgs.GetArg( | ||||
"-limitdescendantcount", | "-limitdescendantcount", | ||||
GetDefaultDescendantLimit(consensusParams, chainActive.Tip())); | GetDefaultDescendantLimit(consensusParams, ::ChainActive().Tip())); | ||||
size_t nLimitDescendantSize = | size_t nLimitDescendantSize = | ||||
gArgs.GetArg("-limitdescendantsize", | gArgs.GetArg("-limitdescendantsize", | ||||
DEFAULT_DESCENDANT_SIZE_LIMIT) * | DEFAULT_DESCENDANT_SIZE_LIMIT) * | ||||
1000; | 1000; | ||||
std::string errString; | std::string errString; | ||||
if (!pool.CalculateMemPoolAncestors( | if (!pool.CalculateMemPoolAncestors( | ||||
entry, setAncestors, nLimitAncestors, nLimitAncestorSize, | entry, setAncestors, nLimitAncestors, nLimitAncestorSize, | ||||
nLimitDescendants, nLimitDescendantSize, errString)) { | nLimitDescendants, nLimitDescendantSize, errString)) { | ||||
▲ Show 20 Lines • Show All 119 Lines • ▼ Show 20 Lines | if (!blockIndex) { | ||||
return g_txindex->FindTx(txid, hashBlock, txOut); | return g_txindex->FindTx(txid, hashBlock, txOut); | ||||
} | } | ||||
// use coin database to locate block that contains transaction, and scan | // use coin database to locate block that contains transaction, and scan | ||||
// it | // it | ||||
if (fAllowSlow) { | if (fAllowSlow) { | ||||
const Coin &coin = AccessByTxid(*pcoinsTip, txid); | const Coin &coin = AccessByTxid(*pcoinsTip, txid); | ||||
if (!coin.IsSpent()) { | if (!coin.IsSpent()) { | ||||
pindexSlow = chainActive[coin.GetHeight()]; | pindexSlow = ::ChainActive()[coin.GetHeight()]; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
if (pindexSlow) { | if (pindexSlow) { | ||||
CBlock block; | CBlock block; | ||||
if (ReadBlockFromDisk(block, pindexSlow, params)) { | if (ReadBlockFromDisk(block, pindexSlow, params)) { | ||||
for (const auto &tx : block.vtx) { | for (const auto &tx : block.vtx) { | ||||
▲ Show 20 Lines • Show All 110 Lines • ▼ Show 20 Lines | bool IsInitialBlockDownload() { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
if (latchToFalse.load(std::memory_order_relaxed)) { | if (latchToFalse.load(std::memory_order_relaxed)) { | ||||
return false; | return false; | ||||
} | } | ||||
if (fImporting || fReindex) { | if (fImporting || fReindex) { | ||||
return true; | return true; | ||||
} | } | ||||
if (chainActive.Tip() == nullptr) { | if (::ChainActive().Tip() == nullptr) { | ||||
return true; | return true; | ||||
} | } | ||||
if (chainActive.Tip()->nChainWork < nMinimumChainWork) { | if (::ChainActive().Tip()->nChainWork < nMinimumChainWork) { | ||||
return true; | return true; | ||||
} | } | ||||
if (chainActive.Tip()->GetBlockTime() < (GetTime() - nMaxTipAge)) { | if (::ChainActive().Tip()->GetBlockTime() < (GetTime() - nMaxTipAge)) { | ||||
return true; | return true; | ||||
} | } | ||||
LogPrintf("Leaving InitialBlockDownload (latching to false)\n"); | LogPrintf("Leaving InitialBlockDownload (latching to false)\n"); | ||||
latchToFalse.store(true, std::memory_order_relaxed); | latchToFalse.store(true, std::memory_order_relaxed); | ||||
return false; | return false; | ||||
} | } | ||||
CBlockIndex const *pindexBestForkTip = nullptr; | CBlockIndex const *pindexBestForkTip = nullptr; | ||||
Show All 26 Lines | static void CheckForkWarningConditions() EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
// sync) | // sync) | ||||
if (IsInitialBlockDownload()) { | if (IsInitialBlockDownload()) { | ||||
return; | return; | ||||
} | } | ||||
// If our best fork is no longer within 72 blocks (+/- 12 hours if no one | // If our best fork is no longer within 72 blocks (+/- 12 hours if no one | ||||
// mines it) of our head, drop it | // mines it) of our head, drop it | ||||
if (pindexBestForkTip && | if (pindexBestForkTip && | ||||
chainActive.Height() - pindexBestForkTip->nHeight >= 72) { | ::ChainActive().Height() - pindexBestForkTip->nHeight >= 72) { | ||||
pindexBestForkTip = nullptr; | pindexBestForkTip = nullptr; | ||||
} | } | ||||
if (pindexBestForkTip || | if (pindexBestForkTip || | ||||
(pindexBestInvalid && | (pindexBestInvalid && | ||||
pindexBestInvalid->nChainWork > | pindexBestInvalid->nChainWork > | ||||
chainActive.Tip()->nChainWork + | ::ChainActive().Tip()->nChainWork + | ||||
(GetBlockProof(*chainActive.Tip()) * 6))) { | (GetBlockProof(*::ChainActive().Tip()) * 6))) { | ||||
if (!GetfLargeWorkForkFound() && pindexBestForkBase) { | if (!GetfLargeWorkForkFound() && pindexBestForkBase) { | ||||
std::string warning = | std::string warning = | ||||
std::string("'Warning: Large-work fork detected, forking after " | std::string("'Warning: Large-work fork detected, forking after " | ||||
"block ") + | "block ") + | ||||
pindexBestForkBase->phashBlock->ToString() + std::string("'"); | pindexBestForkBase->phashBlock->ToString() + std::string("'"); | ||||
AlertNotify(warning); | AlertNotify(warning); | ||||
} | } | ||||
Show All 18 Lines | if (pindexBestForkTip || | ||||
SetfLargeWorkInvalidChainFound(false); | SetfLargeWorkInvalidChainFound(false); | ||||
} | } | ||||
} | } | ||||
static void CheckForkWarningConditionsOnNewFork(CBlockIndex *pindexNewForkTip) | static void CheckForkWarningConditionsOnNewFork(CBlockIndex *pindexNewForkTip) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
// 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. | ||||
const CBlockIndex *pfork = chainActive.FindFork(pindexNewForkTip); | const CBlockIndex *pfork = ::ChainActive().FindFork(pindexNewForkTip); | ||||
// We define a condition where we should warn the user about as a fork of at | // We define a condition where we should warn the user about as a fork of at | ||||
// least 7 blocks with a tip within 72 blocks (+/- 12 hours if no one mines | // least 7 blocks with a tip within 72 blocks (+/- 12 hours if no one mines | ||||
// it) of ours. We use 7 blocks rather arbitrarily as it represents just | // it) of ours. We use 7 blocks rather arbitrarily as it represents just | ||||
// under 10% of sustained network hash rate operating on the fork, or a | // under 10% of sustained network hash rate operating on the fork, or a | ||||
// chain that is entirely longer than ours and invalid (note that this | // chain that is entirely longer than ours and invalid (note that this | ||||
// should be detected by both). We define it this way because it allows us | // should be detected by both). We define it this way because it allows us | ||||
// to only store the highest fork tip (+ base) which meets the 7-block | // to only store the highest fork tip (+ base) which meets the 7-block | ||||
// condition and from this always have the most-likely-to-cause-warning fork | // condition and from this always have the most-likely-to-cause-warning fork | ||||
if (pfork && | if (pfork && | ||||
(!pindexBestForkTip || | (!pindexBestForkTip || | ||||
pindexNewForkTip->nHeight > pindexBestForkTip->nHeight) && | pindexNewForkTip->nHeight > pindexBestForkTip->nHeight) && | ||||
pindexNewForkTip->nChainWork - pfork->nChainWork > | pindexNewForkTip->nChainWork - pfork->nChainWork > | ||||
(GetBlockProof(*pfork) * 7) && | (GetBlockProof(*pfork) * 7) && | ||||
chainActive.Height() - pindexNewForkTip->nHeight < 72) { | ::ChainActive().Height() - pindexNewForkTip->nHeight < 72) { | ||||
pindexBestForkTip = pindexNewForkTip; | pindexBestForkTip = pindexNewForkTip; | ||||
pindexBestForkBase = pfork; | pindexBestForkBase = pfork; | ||||
} | } | ||||
CheckForkWarningConditions(); | CheckForkWarningConditions(); | ||||
} | } | ||||
static void InvalidChainFound(CBlockIndex *pindexNew) | static void InvalidChainFound(CBlockIndex *pindexNew) | ||||
Show All 10 Lines | if (IsBlockFinalized(pindexNew)) { | ||||
pindexFinalized = pindexNew->pprev; | pindexFinalized = pindexNew->pprev; | ||||
} | } | ||||
LogPrintf("%s: invalid block=%s height=%d log2_work=%.8g date=%s\n", | LogPrintf("%s: invalid block=%s height=%d log2_work=%.8g date=%s\n", | ||||
__func__, pindexNew->GetBlockHash().ToString(), | __func__, pindexNew->GetBlockHash().ToString(), | ||||
pindexNew->nHeight, | pindexNew->nHeight, | ||||
log(pindexNew->nChainWork.getdouble()) / log(2.0), | log(pindexNew->nChainWork.getdouble()) / log(2.0), | ||||
FormatISO8601DateTime(pindexNew->GetBlockTime())); | FormatISO8601DateTime(pindexNew->GetBlockTime())); | ||||
CBlockIndex *tip = chainActive.Tip(); | CBlockIndex *tip = ::ChainActive().Tip(); | ||||
assert(tip); | assert(tip); | ||||
LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", | LogPrintf("%s: current best=%s height=%d log2_work=%.8g date=%s\n", | ||||
__func__, tip->GetBlockHash().ToString(), chainActive.Height(), | __func__, tip->GetBlockHash().ToString(), | ||||
::ChainActive().Height(), | |||||
log(tip->nChainWork.getdouble()) / log(2.0), | log(tip->nChainWork.getdouble()) / log(2.0), | ||||
FormatISO8601DateTime(tip->GetBlockTime())); | FormatISO8601DateTime(tip->GetBlockTime())); | ||||
} | } | ||||
void CChainState::InvalidBlockFound(CBlockIndex *pindex, | void CChainState::InvalidBlockFound(CBlockIndex *pindex, | ||||
const CValidationState &state) { | const CValidationState &state) { | ||||
if (!state.CorruptionPossible()) { | if (!state.CorruptionPossible()) { | ||||
pindex->nStatus = pindex->nStatus.withFailed(); | pindex->nStatus = pindex->nStatus.withFailed(); | ||||
▲ Show 20 Lines • Show All 1,085 Lines • ▼ Show 20 Lines | try { | ||||
} | } | ||||
nLastFlush = nNow; | nLastFlush = nNow; | ||||
full_flush_completed = true; | full_flush_completed = true; | ||||
} | } | ||||
} | } | ||||
if (full_flush_completed) { | if (full_flush_completed) { | ||||
// Update best block in wallet (so we can detect restored wallets). | // Update best block in wallet (so we can detect restored wallets). | ||||
GetMainSignals().ChainStateFlushed(chainActive.GetLocator()); | GetMainSignals().ChainStateFlushed(::ChainActive().GetLocator()); | ||||
} | } | ||||
} catch (const std::runtime_error &e) { | } catch (const std::runtime_error &e) { | ||||
return AbortNode(state, std::string("System error while flushing: ") + | return AbortNode(state, std::string("System error while flushing: ") + | ||||
e.what()); | e.what()); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 109 Lines • ▼ Show 20 Lines | bool CChainState::DisconnectTip(const Config &config, CValidationState &state, | ||||
// If the tip is finalized, then undo it. | // If the tip is finalized, then undo it. | ||||
if (pindexFinalized == pindexDelete) { | if (pindexFinalized == pindexDelete) { | ||||
pindexFinalized = pindexDelete->pprev; | pindexFinalized = pindexDelete->pprev; | ||||
} | } | ||||
m_chain.SetTip(pindexDelete->pprev); | m_chain.SetTip(pindexDelete->pprev); | ||||
// Update chainActive and related variables. | // Update ::ChainActive() and related variables. | ||||
UpdateTip(config, pindexDelete->pprev); | UpdateTip(config, pindexDelete->pprev); | ||||
// 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: | ||||
GetMainSignals().BlockDisconnected(pblock); | GetMainSignals().BlockDisconnected(pblock); | ||||
return true; | return true; | ||||
} | } | ||||
static int64_t nTimeReadFromDisk = 0; | static int64_t nTimeReadFromDisk = 0; | ||||
▲ Show 20 Lines • Show All 905 Lines • ▼ Show 20 Lines | bool FinalizeBlockAndInvalidate(const Config &config, CValidationState &state, | ||||
} | } | ||||
// We have a valid candidate, make sure it is not parked. | // We have a valid candidate, make sure it is not parked. | ||||
if (pindex->nStatus.isOnParkedChain()) { | if (pindex->nStatus.isOnParkedChain()) { | ||||
UnparkBlock(pindex); | UnparkBlock(pindex); | ||||
} | } | ||||
// If the finalized block is not on the active chain, we may need to rewind. | // If the finalized block is not on the active chain, we may need to rewind. | ||||
if (!chainActive.Contains(pindex)) { | if (!::ChainActive().Contains(pindex)) { | ||||
const CBlockIndex *pindexFork = chainActive.FindFork(pindex); | const CBlockIndex *pindexFork = ::ChainActive().FindFork(pindex); | ||||
CBlockIndex *pindexToInvalidate = chainActive.Next(pindexFork); | CBlockIndex *pindexToInvalidate = ::ChainActive().Next(pindexFork); | ||||
if (pindexToInvalidate) { | if (pindexToInvalidate) { | ||||
return InvalidateBlock(config, state, pindexToInvalidate); | return InvalidateBlock(config, state, pindexToInvalidate); | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
Show All 17 Lines | if (pindex->nStatus != newStatus && | ||||
pindex->nStatus = newStatus; | pindex->nStatus = newStatus; | ||||
setDirtyBlockIndex.insert(pindex); | setDirtyBlockIndex.insert(pindex); | ||||
if (newStatus.isValid()) { | if (newStatus.isValid()) { | ||||
m_failed_blocks.erase(pindex); | m_failed_blocks.erase(pindex); | ||||
} | } | ||||
if (pindex->IsValid(BlockValidity::TRANSACTIONS) && | if (pindex->IsValid(BlockValidity::TRANSACTIONS) && | ||||
pindex->HaveTxsDownloaded() && | pindex->HaveTxsDownloaded() && | ||||
setBlockIndexCandidates.value_comp()(chainActive.Tip(), pindex)) { | setBlockIndexCandidates.value_comp()(::ChainActive().Tip(), | ||||
pindex)) { | |||||
setBlockIndexCandidates.insert(pindex); | setBlockIndexCandidates.insert(pindex); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
return false; | return false; | ||||
} | } | ||||
template <typename F, typename C, typename AC> | template <typename F, typename C, typename AC> | ||||
▲ Show 20 Lines • Show All 467 Lines • ▼ Show 20 Lines | bool ContextualCheckTransactionForCurrentBlock(const Consensus::Params ¶ms, | ||||
// By convention a negative value for flags indicates that the current | // By convention a negative value for flags indicates that the current | ||||
// network-enforced consensus rules should be used. In a future soft-fork | // network-enforced consensus rules should be used. In a future soft-fork | ||||
// scenario that would mean checking which rules would be enforced for the | // scenario that would mean checking which rules would be enforced for the | ||||
// next block and setting the appropriate flags. At the present time no | // next block and setting the appropriate flags. At the present time no | ||||
// soft-forks are scheduled, so no flags are set. | // soft-forks are scheduled, so no flags are set. | ||||
flags = std::max(flags, 0); | flags = std::max(flags, 0); | ||||
// ContextualCheckTransactionForCurrentBlock() uses chainActive.Height()+1 | // ContextualCheckTransactionForCurrentBlock() uses | ||||
// to evaluate nLockTime because when IsFinalTx() is called within | // ::ChainActive().Height()+1 to evaluate nLockTime because when IsFinalTx() | ||||
// CBlock::AcceptBlock(), the height of the block *being* evaluated is what | // is called within CBlock::AcceptBlock(), the height of the block *being* | ||||
// is used. Thus if we want to know if a transaction can be part of the | // evaluated is what is used. Thus if we want to know if a transaction can | ||||
// *next* block, we need to call ContextualCheckTransaction() with one more | // be part of the *next* block, we need to call ContextualCheckTransaction() | ||||
// than chainActive.Height(). | // with one more than ::ChainActive().Height(). | ||||
const int nBlockHeight = chainActive.Height() + 1; | const int nBlockHeight = ::ChainActive().Height() + 1; | ||||
// BIP113 will require that time-locked transactions have nLockTime set to | // BIP113 will require that time-locked transactions have nLockTime set to | ||||
// less than the median time of the previous block they're contained in. | // less than the median time of the previous block they're contained in. | ||||
// When the next block is created its previous block will be the current | // When the next block is created its previous block will be the current | ||||
// chain tip, so we use that to calculate the median time passed to | // chain tip, so we use that to calculate the median time passed to | ||||
// ContextualCheckTransaction() if LOCKTIME_MEDIAN_TIME_PAST is set. | // ContextualCheckTransaction() if LOCKTIME_MEDIAN_TIME_PAST is set. | ||||
const int64_t nMedianTimePast = | const int64_t nMedianTimePast = | ||||
chainActive.Tip() == nullptr ? 0 | ::ChainActive().Tip() == nullptr | ||||
: chainActive.Tip()->GetMedianTimePast(); | ? 0 | ||||
: ::ChainActive().Tip()->GetMedianTimePast(); | |||||
const int64_t nLockTimeCutoff = (flags & LOCKTIME_MEDIAN_TIME_PAST) | const int64_t nLockTimeCutoff = (flags & LOCKTIME_MEDIAN_TIME_PAST) | ||||
? nMedianTimePast | ? nMedianTimePast | ||||
: GetAdjustedTime(); | : GetAdjustedTime(); | ||||
return ContextualCheckTransaction(params, tx, state, nBlockHeight, | return ContextualCheckTransaction(params, tx, state, nBlockHeight, | ||||
nLockTimeCutoff, nMedianTimePast); | nLockTimeCutoff, nMedianTimePast); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 483 Lines • ▼ Show 20 Lines | bool ProcessNewBlock(const Config &config, | ||||
return true; | return true; | ||||
} | } | ||||
bool TestBlockValidity(CValidationState &state, const CChainParams ¶ms, | bool TestBlockValidity(CValidationState &state, const CChainParams ¶ms, | ||||
const CBlock &block, CBlockIndex *pindexPrev, | const CBlock &block, CBlockIndex *pindexPrev, | ||||
BlockValidationOptions validationOptions) { | BlockValidationOptions validationOptions) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
assert(pindexPrev && pindexPrev == chainActive.Tip()); | assert(pindexPrev && pindexPrev == ::ChainActive().Tip()); | ||||
CCoinsViewCache viewNew(pcoinsTip.get()); | CCoinsViewCache viewNew(pcoinsTip.get()); | ||||
BlockHash block_hash(block.GetHash()); | BlockHash block_hash(block.GetHash()); | ||||
CBlockIndex indexDummy(block); | CBlockIndex indexDummy(block); | ||||
indexDummy.pprev = pindexPrev; | indexDummy.pprev = pindexPrev; | ||||
indexDummy.nHeight = pindexPrev->nHeight + 1; | indexDummy.nHeight = pindexPrev->nHeight + 1; | ||||
indexDummy.phashBlock = &block_hash; | indexDummy.phashBlock = &block_hash; | ||||
// NOTE: CheckBlockHeader is called by CheckBlock | // NOTE: CheckBlockHeader is called by CheckBlock | ||||
▲ Show 20 Lines • Show All 91 Lines • ▼ Show 20 Lines | |||||
* Calculate the block/rev files to delete based on height specified by user | * Calculate the block/rev files to delete based on height specified by user | ||||
* with RPC command pruneblockchain | * with RPC command pruneblockchain | ||||
*/ | */ | ||||
static void FindFilesToPruneManual(std::set<int> &setFilesToPrune, | static void FindFilesToPruneManual(std::set<int> &setFilesToPrune, | ||||
int nManualPruneHeight) { | int nManualPruneHeight) { | ||||
assert(fPruneMode && nManualPruneHeight > 0); | assert(fPruneMode && nManualPruneHeight > 0); | ||||
LOCK2(cs_main, cs_LastBlockFile); | LOCK2(cs_main, cs_LastBlockFile); | ||||
if (chainActive.Tip() == nullptr) { | if (::ChainActive().Tip() == nullptr) { | ||||
return; | return; | ||||
} | } | ||||
// last block to prune is the lesser of (user-specified height, | // last block to prune is the lesser of (user-specified height, | ||||
// MIN_BLOCKS_TO_KEEP from the tip) | // MIN_BLOCKS_TO_KEEP from the tip) | ||||
unsigned int nLastBlockWeCanPrune = | unsigned int nLastBlockWeCanPrune = | ||||
std::min((unsigned)nManualPruneHeight, | std::min((unsigned)nManualPruneHeight, | ||||
chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP); | ::ChainActive().Tip()->nHeight - MIN_BLOCKS_TO_KEEP); | ||||
int count = 0; | int count = 0; | ||||
for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) { | for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) { | ||||
if (vinfoBlockFile[fileNumber].nSize == 0 || | if (vinfoBlockFile[fileNumber].nSize == 0 || | ||||
vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune) { | vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune) { | ||||
continue; | continue; | ||||
} | } | ||||
PruneOneBlockFile(fileNumber); | PruneOneBlockFile(fileNumber); | ||||
setFilesToPrune.insert(fileNumber); | setFilesToPrune.insert(fileNumber); | ||||
Show All 33 Lines | |||||
* least some block files have been pruned. | * least some block files have been pruned. | ||||
* | * | ||||
* @param[out] setFilesToPrune The set of file indices that can be unlinked | * @param[out] setFilesToPrune The set of file indices that can be unlinked | ||||
* will be returned | * will be returned | ||||
*/ | */ | ||||
static void FindFilesToPrune(std::set<int> &setFilesToPrune, | static void FindFilesToPrune(std::set<int> &setFilesToPrune, | ||||
uint64_t nPruneAfterHeight) { | uint64_t nPruneAfterHeight) { | ||||
LOCK2(cs_main, cs_LastBlockFile); | LOCK2(cs_main, cs_LastBlockFile); | ||||
if (chainActive.Tip() == nullptr || nPruneTarget == 0) { | if (::ChainActive().Tip() == nullptr || nPruneTarget == 0) { | ||||
return; | return; | ||||
} | } | ||||
if (uint64_t(chainActive.Tip()->nHeight) <= nPruneAfterHeight) { | if (uint64_t(::ChainActive().Tip()->nHeight) <= nPruneAfterHeight) { | ||||
return; | return; | ||||
} | } | ||||
unsigned int nLastBlockWeCanPrune = | unsigned int nLastBlockWeCanPrune = | ||||
chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP; | ::ChainActive().Tip()->nHeight - MIN_BLOCKS_TO_KEEP; | ||||
uint64_t nCurrentUsage = CalculateCurrentUsage(); | uint64_t nCurrentUsage = CalculateCurrentUsage(); | ||||
// We don't check to prune until after we've allocated new space for files, | // We don't check to prune until after we've allocated new space for files, | ||||
// so we should leave a buffer under our target to account for another | // so we should leave a buffer under our target to account for another | ||||
// allocation before the next pruning. | // allocation before the next pruning. | ||||
uint64_t nBuffer = BLOCKFILE_CHUNK_SIZE + UNDOFILE_CHUNK_SIZE; | uint64_t nBuffer = BLOCKFILE_CHUNK_SIZE + UNDOFILE_CHUNK_SIZE; | ||||
uint64_t nBytesToPrune; | uint64_t nBytesToPrune; | ||||
int count = 0; | int count = 0; | ||||
▲ Show 20 Lines • Show All 225 Lines • ▼ Show 20 Lines | static bool LoadBlockIndexDB(const Config &config) | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
bool LoadChainTip(const Config &config) { | bool LoadChainTip(const Config &config) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
if (chainActive.Tip() && | if (::ChainActive().Tip() && | ||||
chainActive.Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) { | ::ChainActive().Tip()->GetBlockHash() == pcoinsTip->GetBestBlock()) { | ||||
return true; | return true; | ||||
} | } | ||||
if (pcoinsTip->GetBestBlock().IsNull() && mapBlockIndex.size() == 1) { | if (pcoinsTip->GetBestBlock().IsNull() && mapBlockIndex.size() == 1) { | ||||
// In case we just added the genesis block, connect it now, so | // In case we just added the genesis block, connect it now, so | ||||
// that we always have a chainActive.Tip() when we return. | // that we always have a ::ChainActive().Tip() when we return. | ||||
LogPrintf("%s: Connecting genesis block...\n", __func__); | LogPrintf("%s: Connecting genesis block...\n", __func__); | ||||
CValidationState state; | CValidationState state; | ||||
if (!ActivateBestChain(config, state)) { | if (!ActivateBestChain(config, state)) { | ||||
LogPrintf("%s: failed to activate chain (%s)\n", __func__, | LogPrintf("%s: failed to activate chain (%s)\n", __func__, | ||||
FormatStateMessage(state)); | FormatStateMessage(state)); | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
// Load pointer to end of best chain | // Load pointer to end of best chain | ||||
CBlockIndex *pindex = LookupBlockIndex(pcoinsTip->GetBestBlock()); | CBlockIndex *pindex = LookupBlockIndex(pcoinsTip->GetBestBlock()); | ||||
if (!pindex) { | if (!pindex) { | ||||
return false; | return false; | ||||
} | } | ||||
chainActive.SetTip(pindex); | ::ChainActive().SetTip(pindex); | ||||
g_chainstate.PruneBlockIndexCandidates(); | g_chainstate.PruneBlockIndexCandidates(); | ||||
LogPrintf( | LogPrintf( | ||||
"Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n", | "Loaded best chain: hashBestChain=%s height=%d date=%s progress=%f\n", | ||||
chainActive.Tip()->GetBlockHash().ToString(), chainActive.Height(), | ::ChainActive().Tip()->GetBlockHash().ToString(), | ||||
FormatISO8601DateTime(chainActive.Tip()->GetBlockTime()), | ::ChainActive().Height(), | ||||
FormatISO8601DateTime(::ChainActive().Tip()->GetBlockTime()), | |||||
GuessVerificationProgress(config.GetChainParams().TxData(), | GuessVerificationProgress(config.GetChainParams().TxData(), | ||||
chainActive.Tip())); | ::ChainActive().Tip())); | ||||
return true; | return true; | ||||
} | } | ||||
CVerifyDB::CVerifyDB() { | CVerifyDB::CVerifyDB() { | ||||
uiInterface.ShowProgress(_("Verifying blocks..."), 0, false); | uiInterface.ShowProgress(_("Verifying blocks..."), 0, false); | ||||
} | } | ||||
CVerifyDB::~CVerifyDB() { | CVerifyDB::~CVerifyDB() { | ||||
uiInterface.ShowProgress("", 100, false); | uiInterface.ShowProgress("", 100, false); | ||||
} | } | ||||
bool CVerifyDB::VerifyDB(const Config &config, CCoinsView *coinsview, | bool CVerifyDB::VerifyDB(const Config &config, CCoinsView *coinsview, | ||||
int nCheckLevel, int nCheckDepth) { | int nCheckLevel, int nCheckDepth) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const CChainParams ¶ms = config.GetChainParams(); | const CChainParams ¶ms = config.GetChainParams(); | ||||
const Consensus::Params &consensusParams = params.GetConsensus(); | const Consensus::Params &consensusParams = params.GetConsensus(); | ||||
if (chainActive.Tip() == nullptr || chainActive.Tip()->pprev == nullptr) { | if (::ChainActive().Tip() == nullptr || | ||||
::ChainActive().Tip()->pprev == nullptr) { | |||||
return true; | return true; | ||||
} | } | ||||
// Verify blocks in the best chain | // Verify blocks in the best chain | ||||
if (nCheckDepth <= 0 || nCheckDepth > chainActive.Height()) { | if (nCheckDepth <= 0 || nCheckDepth > ::ChainActive().Height()) { | ||||
nCheckDepth = chainActive.Height(); | 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, | LogPrintf("Verifying last %i blocks at level %i\n", nCheckDepth, | ||||
nCheckLevel); | nCheckLevel); | ||||
CCoinsViewCache coins(coinsview); | CCoinsViewCache coins(coinsview); | ||||
CBlockIndex *pindex; | CBlockIndex *pindex; | ||||
CBlockIndex *pindexFailure = nullptr; | CBlockIndex *pindexFailure = nullptr; | ||||
int nGoodTransactions = 0; | int nGoodTransactions = 0; | ||||
CValidationState state; | CValidationState state; | ||||
int reportDone = 0; | int reportDone = 0; | ||||
LogPrintfToBeContinued("[0%%]..."); | LogPrintfToBeContinued("[0%%]..."); | ||||
for (pindex = chainActive.Tip(); pindex && pindex->pprev; | for (pindex = ::ChainActive().Tip(); pindex && pindex->pprev; | ||||
pindex = pindex->pprev) { | pindex = pindex->pprev) { | ||||
boost::this_thread::interruption_point(); | boost::this_thread::interruption_point(); | ||||
int percentageDone = std::max( | int percentageDone = | ||||
1, std::min( | std::max(1, std::min(99, (int)(((double)(::ChainActive().Height() - | ||||
99, | pindex->nHeight)) / | ||||
(int)(((double)(chainActive.Height() - pindex->nHeight)) / | (double)nCheckDepth * | ||||
(double)nCheckDepth * (nCheckLevel >= 4 ? 50 : 100)))); | (nCheckLevel >= 4 ? 50 : 100)))); | ||||
if (reportDone < percentageDone / 10) { | if (reportDone < percentageDone / 10) { | ||||
// report every 10% step | // report every 10% step | ||||
LogPrintfToBeContinued("[%d%%]...", percentageDone); | LogPrintfToBeContinued("[%d%%]...", percentageDone); | ||||
reportDone = percentageDone / 10; | reportDone = percentageDone / 10; | ||||
} | } | ||||
uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone, | uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone, | ||||
false); | false); | ||||
if (pindex->nHeight <= chainActive.Height() - nCheckDepth) { | if (pindex->nHeight <= ::ChainActive().Height() - nCheckDepth) { | ||||
break; | break; | ||||
} | } | ||||
if (fPruneMode && !pindex->nStatus.hasData()) { | if (fPruneMode && !pindex->nStatus.hasData()) { | ||||
// If pruning, only go back as far as we have data. | // If pruning, only go back as far as we have data. | ||||
LogPrintf("VerifyDB(): block verification stopping at height %d " | LogPrintf("VerifyDB(): block verification stopping at height %d " | ||||
"(pruning, no data)\n", | "(pruning, no data)\n", | ||||
pindex->nHeight); | pindex->nHeight); | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | for (pindex = ::ChainActive().Tip(); pindex && pindex->pprev; | ||||
if (ShutdownRequested()) { | if (ShutdownRequested()) { | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
if (pindexFailure) { | if (pindexFailure) { | ||||
return error("VerifyDB(): *** coin database inconsistencies found " | return error("VerifyDB(): *** coin database inconsistencies found " | ||||
"(last %i blocks, %i good transactions before that)\n", | "(last %i blocks, %i good transactions before that)\n", | ||||
chainActive.Height() - pindexFailure->nHeight + 1, | ::ChainActive().Height() - pindexFailure->nHeight + 1, | ||||
nGoodTransactions); | nGoodTransactions); | ||||
} | } | ||||
// store block count as we move pindex at check level >= 4 | // store block count as we move pindex at check level >= 4 | ||||
int block_count = chainActive.Height() - pindex->nHeight; | int block_count = ::ChainActive().Height() - pindex->nHeight; | ||||
// check level 4: try reconnecting blocks | // check level 4: try reconnecting blocks | ||||
if (nCheckLevel >= 4) { | if (nCheckLevel >= 4) { | ||||
while (pindex != chainActive.Tip()) { | while (pindex != ::ChainActive().Tip()) { | ||||
boost::this_thread::interruption_point(); | boost::this_thread::interruption_point(); | ||||
uiInterface.ShowProgress( | uiInterface.ShowProgress( | ||||
_("Verifying blocks..."), | _("Verifying blocks..."), | ||||
std::max( | std::max( | ||||
1, std::min(99, 100 - (int)(((double)(chainActive.Height() - | 1, std::min(99, | ||||
100 - (int)(((double)(::ChainActive().Height() - | |||||
pindex->nHeight)) / | pindex->nHeight)) / | ||||
(double)nCheckDepth * 50))), | (double)nCheckDepth * 50))), | ||||
false); | false); | ||||
pindex = chainActive.Next(pindex); | pindex = ::ChainActive().Next(pindex); | ||||
CBlock block; | CBlock block; | ||||
if (!ReadBlockFromDisk(block, pindex, consensusParams)) { | if (!ReadBlockFromDisk(block, pindex, consensusParams)) { | ||||
return error( | return error( | ||||
"VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", | "VerifyDB(): *** ReadBlockFromDisk failed at %d, hash=%s", | ||||
pindex->nHeight, pindex->GetBlockHash().ToString()); | pindex->nHeight, pindex->GetBlockHash().ToString()); | ||||
} | } | ||||
if (!g_chainstate.ConnectBlock(block, state, pindex, coins, params, | if (!g_chainstate.ConnectBlock(block, state, pindex, coins, params, | ||||
BlockValidationOptions(config))) { | BlockValidationOptions(config))) { | ||||
▲ Show 20 Lines • Show All 152 Lines • ▼ Show 20 Lines | void CChainState::UnloadBlockIndex() { | ||||
setBlockIndexCandidates.clear(); | setBlockIndexCandidates.clear(); | ||||
} | } | ||||
// May NOT be used after any connections are up as much | // May NOT be used after any connections are up as much | ||||
// of the peer-processing logic assumes a consistent | // of the peer-processing logic assumes a consistent | ||||
// block index state | // block index state | ||||
void UnloadBlockIndex() { | void UnloadBlockIndex() { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
chainActive.SetTip(nullptr); | ::ChainActive().SetTip(nullptr); | ||||
pindexFinalized = nullptr; | pindexFinalized = nullptr; | ||||
pindexBestInvalid = nullptr; | pindexBestInvalid = nullptr; | ||||
pindexBestParked = nullptr; | pindexBestParked = nullptr; | ||||
pindexBestHeader = nullptr; | pindexBestHeader = nullptr; | ||||
pindexBestForkTip = nullptr; | pindexBestForkTip = nullptr; | ||||
pindexBestForkBase = nullptr; | pindexBestForkBase = nullptr; | ||||
g_mempool.clear(); | g_mempool.clear(); | ||||
mapBlocksUnlinked.clear(); | mapBlocksUnlinked.clear(); | ||||
▲ Show 20 Lines • Show All 566 Lines • ▼ Show 20 Lines | static ThresholdState VersionBitsStateImpl(const Consensus::Params ¶ms, | ||||
const CBlockIndex *pindex) | const CBlockIndex *pindex) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
return VersionBitsState(pindex, params, pos, versionbitscache); | return VersionBitsState(pindex, params, pos, versionbitscache); | ||||
} | } | ||||
ThresholdState VersionBitsTipState(const Consensus::Params ¶ms, | ThresholdState VersionBitsTipState(const Consensus::Params ¶ms, | ||||
Consensus::DeploymentPos pos) { | Consensus::DeploymentPos pos) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return VersionBitsStateImpl(params, pos, chainActive.Tip()); | return VersionBitsStateImpl(params, pos, ::ChainActive().Tip()); | ||||
} | } | ||||
ThresholdState VersionBitsBlockState(const Consensus::Params ¶ms, | ThresholdState VersionBitsBlockState(const Consensus::Params ¶ms, | ||||
Consensus::DeploymentPos pos, | Consensus::DeploymentPos pos, | ||||
const CBlockIndex *pindex) { | const CBlockIndex *pindex) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return VersionBitsStateImpl(params, pos, pindex); | return VersionBitsStateImpl(params, pos, pindex); | ||||
} | } | ||||
BIP9Stats VersionBitsTipStatistics(const Consensus::Params ¶ms, | BIP9Stats VersionBitsTipStatistics(const Consensus::Params ¶ms, | ||||
Consensus::DeploymentPos pos) { | Consensus::DeploymentPos pos) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return VersionBitsStatistics(chainActive.Tip(), params, pos); | return VersionBitsStatistics(::ChainActive().Tip(), params, pos); | ||||
} | } | ||||
int VersionBitsTipStateSinceHeight(const Consensus::Params ¶ms, | int VersionBitsTipStateSinceHeight(const Consensus::Params ¶ms, | ||||
Consensus::DeploymentPos pos) { | Consensus::DeploymentPos pos) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return VersionBitsStateSinceHeight(chainActive.Tip(), params, pos, | return VersionBitsStateSinceHeight(::ChainActive().Tip(), params, pos, | ||||
versionbitscache); | versionbitscache); | ||||
} | } | ||||
static const uint64_t MEMPOOL_DUMP_VERSION = 1; | static const uint64_t MEMPOOL_DUMP_VERSION = 1; | ||||
bool LoadMempool(const Config &config, CTxMemPool &pool) { | bool LoadMempool(const Config &config, CTxMemPool &pool) { | ||||
int64_t nExpiryTimeout = | int64_t nExpiryTimeout = | ||||
gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60; | gArgs.GetArg("-mempoolexpiry", DEFAULT_MEMPOOL_EXPIRY) * 60 * 60; | ||||
▲ Show 20 Lines • Show All 179 Lines • Show Last 20 Lines |