Changeset View
Changeset View
Standalone View
Standalone View
src/validation.cpp
Show First 20 Lines • Show All 203 Lines • ▼ Show 20 Lines | bool ConnectTip(const Config &config, CValidationState &state, | ||||
const std::shared_ptr<const CBlock> &pblock, | const std::shared_ptr<const CBlock> &pblock, | ||||
ConnectTrace &connectTrace, | ConnectTrace &connectTrace, | ||||
DisconnectedBlockTransactions &disconnectpool) | DisconnectedBlockTransactions &disconnectpool) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
CBlockIndex *AddToBlockIndex(const CBlockHeader &block) | CBlockIndex *AddToBlockIndex(const CBlockHeader &block) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
/** Create a new block index entry for a given block hash */ | /** Create a new block index entry for a given block hash */ | ||||
CBlockIndex *InsertBlockIndex(const uint256 &hash) | CBlockIndex *InsertBlockIndex(const BlockHash &hash) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main); | EXCLUSIVE_LOCKS_REQUIRED(cs_main); | ||||
/** | /** | ||||
* Make various assertions about the state of the block index. | * Make various assertions about the state of the block index. | ||||
* | * | ||||
* By default this only executes fully when using the Regtest chain; see: | * By default this only executes fully when using the Regtest chain; see: | ||||
* fCheckBlockIndex. | * fCheckBlockIndex. | ||||
*/ | */ | ||||
void CheckBlockIndex(const Consensus::Params &consensusParams); | void CheckBlockIndex(const Consensus::Params &consensusParams); | ||||
Show All 39 Lines | |||||
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG; | bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG; | ||||
bool fRequireStandard = true; | bool fRequireStandard = true; | ||||
bool fCheckBlockIndex = false; | bool fCheckBlockIndex = false; | ||||
bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; | bool fCheckpointsEnabled = DEFAULT_CHECKPOINTS_ENABLED; | ||||
size_t nCoinCacheUsage = 5000 * 300; | size_t nCoinCacheUsage = 5000 * 300; | ||||
uint64_t nPruneTarget = 0; | uint64_t nPruneTarget = 0; | ||||
int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; | int64_t nMaxTipAge = DEFAULT_MAX_TIP_AGE; | ||||
uint256 hashAssumeValid; | BlockHash hashAssumeValid; | ||||
arith_uint256 nMinimumChainWork; | arith_uint256 nMinimumChainWork; | ||||
CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE_PER_KB); | CFeeRate minRelayTxFee = CFeeRate(DEFAULT_MIN_RELAY_TX_FEE_PER_KB); | ||||
Amount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; | Amount maxTxFee = DEFAULT_TRANSACTION_MAXFEE; | ||||
CTxMemPool g_mempool; | CTxMemPool g_mempool; | ||||
/** Constant stuff for coinbase transactions we create: */ | /** Constant stuff for coinbase transactions we create: */ | ||||
Show All 40 Lines | BlockValidationOptions::BlockValidationOptions(const Config &config) | ||||
: excessiveBlockSize(config.GetMaxBlockSize()), checkPoW(true), | : excessiveBlockSize(config.GetMaxBlockSize()), checkPoW(true), | ||||
checkMerkleRoot(true) {} | checkMerkleRoot(true) {} | ||||
CBlockIndex *FindForkInGlobalIndex(const CChain &chain, | CBlockIndex *FindForkInGlobalIndex(const CChain &chain, | ||||
const CBlockLocator &locator) { | const CBlockLocator &locator) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
// Find the first block the caller has in the main chain | // Find the first block the caller has in the main chain | ||||
for (const uint256 &hash : locator.vHave) { | for (const BlockHash &hash : locator.vHave) { | ||||
CBlockIndex *pindex = LookupBlockIndex(hash); | CBlockIndex *pindex = LookupBlockIndex(hash); | ||||
if (pindex) { | if (pindex) { | ||||
if (chain.Contains(pindex)) { | if (chain.Contains(pindex)) { | ||||
return pindex; | return pindex; | ||||
} | } | ||||
if (pindex->GetAncestor(chain.Height()) == chain.Tip()) { | if (pindex->GetAncestor(chain.Height()) == chain.Tip()) { | ||||
return chain.Tip(); | return chain.Tip(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,387 Lines • ▼ Show 20 Lines | if (!CheckBlock(block, state, consensusParams, | ||||
return AbortNode(state, "Corrupt block found indicating potential " | return AbortNode(state, "Corrupt block found indicating potential " | ||||
"hardware failure; shutting down"); | "hardware failure; shutting down"); | ||||
} | } | ||||
return error("%s: Consensus::CheckBlock: %s", __func__, | return error("%s: Consensus::CheckBlock: %s", __func__, | ||||
FormatStateMessage(state)); | FormatStateMessage(state)); | ||||
} | } | ||||
// Verify that the view's current state corresponds to the previous block | // Verify that the view's current state corresponds to the previous block | ||||
uint256 hashPrevBlock = | BlockHash hashPrevBlock = | ||||
pindex->pprev == nullptr ? uint256() : pindex->pprev->GetBlockHash(); | pindex->pprev == nullptr ? BlockHash() : pindex->pprev->GetBlockHash(); | ||||
assert(hashPrevBlock == view.GetBestBlock()); | assert(hashPrevBlock == view.GetBestBlock()); | ||||
// Special case for the genesis block, skipping connection of its | // Special case for the genesis block, skipping connection of its | ||||
// transactions (its coinbase is unspendable) | // transactions (its coinbase is unspendable) | ||||
if (block.GetHash() == consensusParams.hashGenesisBlock) { | if (block.GetHash() == consensusParams.hashGenesisBlock) { | ||||
if (!fJustCheck) { | if (!fJustCheck) { | ||||
view.SetBestBlock(pindex->GetBlockHash()); | view.SetBestBlock(pindex->GetBlockHash()); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,372 Lines • ▼ Show 20 Lines | bool CChainState::UnwindBlock(const Config &config, CValidationState &state, | ||||
} | } | ||||
// DisconnectTip will add transactions to disconnectpool; try to add these | // DisconnectTip will add transactions to disconnectpool; try to add these | ||||
// back to the mempool. | // back to the mempool. | ||||
disconnectpool.updateMempoolForReorg(config, true); | disconnectpool.updateMempoolForReorg(config, true); | ||||
// The resulting new best tip may not be in setBlockIndexCandidates anymore, | // The resulting new best tip may not be in setBlockIndexCandidates anymore, | ||||
// so add it again. | // so add it again. | ||||
for (const std::pair<const uint256, CBlockIndex *> &it : mapBlockIndex) { | for (const std::pair<const BlockHash, CBlockIndex *> &it : mapBlockIndex) { | ||||
CBlockIndex *i = it.second; | CBlockIndex *i = it.second; | ||||
if (i->IsValid(BlockValidity::TRANSACTIONS) && i->nChainTx && | if (i->IsValid(BlockValidity::TRANSACTIONS) && i->nChainTx && | ||||
!setBlockIndexCandidates.value_comp()(i, chainActive.Tip())) { | !setBlockIndexCandidates.value_comp()(i, chainActive.Tip())) { | ||||
setBlockIndexCandidates.insert(i); | setBlockIndexCandidates.insert(i); | ||||
} | } | ||||
} | } | ||||
if (invalidate) { | if (invalidate) { | ||||
▲ Show 20 Lines • Show All 163 Lines • ▼ Show 20 Lines | return pindexFinalized && | ||||
pindexFinalized->GetAncestor(pindex->nHeight) == pindex; | pindexFinalized->GetAncestor(pindex->nHeight) == pindex; | ||||
} | } | ||||
CBlockIndex *CChainState::AddToBlockIndex(const CBlockHeader &block) | CBlockIndex *CChainState::AddToBlockIndex(const CBlockHeader &block) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
// Check for duplicate | // Check for duplicate | ||||
uint256 hash = block.GetHash(); | BlockHash hash = block.GetHash(); | ||||
BlockMap::iterator it = mapBlockIndex.find(hash); | BlockMap::iterator it = mapBlockIndex.find(hash); | ||||
if (it != mapBlockIndex.end()) { | if (it != mapBlockIndex.end()) { | ||||
return it->second; | return it->second; | ||||
} | } | ||||
// Construct new block index object | // Construct new block index object | ||||
CBlockIndex *pindexNew = new CBlockIndex(block); | CBlockIndex *pindexNew = new CBlockIndex(block); | ||||
// We assign the sequence id to blocks only when the full data is available, | // We assign the sequence id to blocks only when the full data is available, | ||||
▲ Show 20 Lines • Show All 503 Lines • ▼ Show 20 Lines | |||||
bool CChainState::AcceptBlockHeader(const Config &config, | bool CChainState::AcceptBlockHeader(const Config &config, | ||||
const CBlockHeader &block, | const CBlockHeader &block, | ||||
CValidationState &state, | CValidationState &state, | ||||
CBlockIndex **ppindex) { | CBlockIndex **ppindex) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
const CChainParams &chainparams = config.GetChainParams(); | const CChainParams &chainparams = config.GetChainParams(); | ||||
// Check for duplicate | // Check for duplicate | ||||
uint256 hash = block.GetHash(); | BlockHash hash = block.GetHash(); | ||||
BlockMap::iterator miSelf = mapBlockIndex.find(hash); | BlockMap::iterator miSelf = mapBlockIndex.find(hash); | ||||
CBlockIndex *pindex = nullptr; | CBlockIndex *pindex = nullptr; | ||||
if (hash != chainparams.GetConsensus().hashGenesisBlock) { | if (hash != chainparams.GetConsensus().hashGenesisBlock) { | ||||
if (miSelf != mapBlockIndex.end()) { | if (miSelf != mapBlockIndex.end()) { | ||||
// Block header is already known. | // Block header is already known. | ||||
pindex = miSelf->second; | pindex = miSelf->second; | ||||
if (ppindex) { | if (ppindex) { | ||||
*ppindex = pindex; | *ppindex = pindex; | ||||
▲ Show 20 Lines • Show All 363 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
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()); | ||||
uint256 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 | ||||
if (!ContextualCheckBlockHeader(params, block, state, pindexPrev, | if (!ContextualCheckBlockHeader(params, block, state, pindexPrev, | ||||
GetAdjustedTime())) { | GetAdjustedTime())) { | ||||
▲ Show 20 Lines • Show All 231 Lines • ▼ Show 20 Lines | |||||
static FILE *OpenUndoFile(const FlatFilePos &pos, bool fReadOnly) { | static FILE *OpenUndoFile(const FlatFilePos &pos, bool fReadOnly) { | ||||
return UndoFileSeq().Open(pos, fReadOnly); | return UndoFileSeq().Open(pos, fReadOnly); | ||||
} | } | ||||
fs::path GetBlockPosFilename(const FlatFilePos &pos) { | fs::path GetBlockPosFilename(const FlatFilePos &pos) { | ||||
return BlockFileSeq().FileName(pos); | return BlockFileSeq().FileName(pos); | ||||
} | } | ||||
CBlockIndex *CChainState::InsertBlockIndex(const uint256 &hash) { | CBlockIndex *CChainState::InsertBlockIndex(const BlockHash &hash) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
if (hash.IsNull()) { | if (hash.IsNull()) { | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
// Return existing | // Return existing | ||||
BlockMap::iterator mi = mapBlockIndex.find(hash); | BlockMap::iterator mi = mapBlockIndex.find(hash); | ||||
if (mi != mapBlockIndex.end()) { | if (mi != mapBlockIndex.end()) { | ||||
return (*mi).second; | return (*mi).second; | ||||
} | } | ||||
// Create new | // Create new | ||||
CBlockIndex *pindexNew = new CBlockIndex(); | CBlockIndex *pindexNew = new CBlockIndex(); | ||||
mi = mapBlockIndex.insert(std::make_pair(hash, pindexNew)).first; | mi = mapBlockIndex.insert(std::make_pair(hash, pindexNew)).first; | ||||
pindexNew->phashBlock = &((*mi).first); | pindexNew->phashBlock = &((*mi).first); | ||||
return pindexNew; | return pindexNew; | ||||
} | } | ||||
bool CChainState::LoadBlockIndex(const Config &config, | bool CChainState::LoadBlockIndex(const Config &config, | ||||
CBlockTreeDB &blocktree) { | CBlockTreeDB &blocktree) { | ||||
if (!blocktree.LoadBlockIndexGuts( | if (!blocktree.LoadBlockIndexGuts( | ||||
config.GetChainParams().GetConsensus(), | config.GetChainParams().GetConsensus(), | ||||
[this](const uint256 &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | [this](const BlockHash &hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
return this->InsertBlockIndex(hash); | return this->InsertBlockIndex(hash); | ||||
})) { | })) { | ||||
return false; | return false; | ||||
} | } | ||||
boost::this_thread::interruption_point(); | boost::this_thread::interruption_point(); | ||||
// Calculate nChainWork | // Calculate nChainWork | ||||
std::vector<std::pair<int, CBlockIndex *>> vSortedByHeight; | std::vector<std::pair<int, CBlockIndex *>> vSortedByHeight; | ||||
vSortedByHeight.reserve(mapBlockIndex.size()); | vSortedByHeight.reserve(mapBlockIndex.size()); | ||||
for (const std::pair<const uint256, CBlockIndex *> &item : mapBlockIndex) { | for (const std::pair<const BlockHash, CBlockIndex *> &item : | ||||
mapBlockIndex) { | |||||
CBlockIndex *pindex = item.second; | CBlockIndex *pindex = item.second; | ||||
vSortedByHeight.push_back(std::make_pair(pindex->nHeight, pindex)); | vSortedByHeight.push_back(std::make_pair(pindex->nHeight, pindex)); | ||||
} | } | ||||
sort(vSortedByHeight.begin(), vSortedByHeight.end()); | sort(vSortedByHeight.begin(), vSortedByHeight.end()); | ||||
for (const std::pair<int, CBlockIndex *> &item : vSortedByHeight) { | for (const std::pair<int, CBlockIndex *> &item : vSortedByHeight) { | ||||
CBlockIndex *pindex = item.second; | CBlockIndex *pindex = item.second; | ||||
pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + | pindex->nChainWork = (pindex->pprev ? pindex->pprev->nChainWork : 0) + | ||||
▲ Show 20 Lines • Show All 77 Lines • ▼ Show 20 Lines | for (int nFile = nLastBlockFile + 1; true; nFile++) { | ||||
} else { | } else { | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
// Check presence of blk files | // Check presence of blk files | ||||
LogPrintf("Checking all blk files are present...\n"); | LogPrintf("Checking all blk files are present...\n"); | ||||
std::set<int> setBlkDataFiles; | std::set<int> setBlkDataFiles; | ||||
for (const std::pair<const uint256, CBlockIndex *> &item : mapBlockIndex) { | for (const std::pair<const BlockHash, CBlockIndex *> &item : | ||||
mapBlockIndex) { | |||||
CBlockIndex *pindex = item.second; | CBlockIndex *pindex = item.second; | ||||
if (pindex->nStatus.hasData()) { | if (pindex->nStatus.hasData()) { | ||||
setBlkDataFiles.insert(pindex->nFile); | setBlkDataFiles.insert(pindex->nFile); | ||||
} | } | ||||
} | } | ||||
for (const int i : setBlkDataFiles) { | for (const int i : setBlkDataFiles) { | ||||
FlatFilePos pos(i, 0); | FlatFilePos pos(i, 0); | ||||
▲ Show 20 Lines • Show All 259 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
bool CChainState::ReplayBlocks(const Consensus::Params ¶ms, | bool CChainState::ReplayBlocks(const Consensus::Params ¶ms, | ||||
CCoinsView *view) { | CCoinsView *view) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CCoinsViewCache cache(view); | CCoinsViewCache cache(view); | ||||
std::vector<uint256> hashHeads = view->GetHeadBlocks(); | std::vector<BlockHash> hashHeads = view->GetHeadBlocks(); | ||||
if (hashHeads.empty()) { | if (hashHeads.empty()) { | ||||
// We're already in a consistent state. | // We're already in a consistent state. | ||||
return true; | return true; | ||||
} | } | ||||
if (hashHeads.size() != 2) { | if (hashHeads.size() != 2) { | ||||
return error("ReplayBlocks(): unknown inconsistent state"); | return error("ReplayBlocks(): unknown inconsistent state"); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 309 Lines • ▼ Show 20 Lines | try { | ||||
} | } | ||||
blkdat.SetLimit(nBlockPos + nSize); | blkdat.SetLimit(nBlockPos + nSize); | ||||
blkdat.SetPos(nBlockPos); | blkdat.SetPos(nBlockPos); | ||||
std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); | std::shared_ptr<CBlock> pblock = std::make_shared<CBlock>(); | ||||
CBlock &block = *pblock; | CBlock &block = *pblock; | ||||
blkdat >> block; | blkdat >> block; | ||||
nRewind = blkdat.GetPos(); | nRewind = blkdat.GetPos(); | ||||
uint256 hash = block.GetHash(); | const BlockHash hash = block.GetHash(); | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
// detect out of order blocks, and store them for later | // detect out of order blocks, and store them for later | ||||
if (hash != chainparams.GetConsensus().hashGenesisBlock && | if (hash != chainparams.GetConsensus().hashGenesisBlock && | ||||
!LookupBlockIndex(block.hashPrevBlock)) { | !LookupBlockIndex(block.hashPrevBlock)) { | ||||
LogPrint( | LogPrint( | ||||
BCLog::REINDEX, | BCLog::REINDEX, | ||||
"%s: Out of order block %s, parent %s not known\n", | "%s: Out of order block %s, parent %s not known\n", | ||||
▲ Show 20 Lines • Show All 591 Lines • ▼ Show 20 Lines | double GuessVerificationProgress(const ChainTxData &data, | ||||
return pindex->nChainTx / fTxTotal; | return pindex->nChainTx / fTxTotal; | ||||
} | } | ||||
class CMainCleanup { | class CMainCleanup { | ||||
public: | public: | ||||
CMainCleanup() {} | CMainCleanup() {} | ||||
~CMainCleanup() { | ~CMainCleanup() { | ||||
// block headers | // block headers | ||||
for (const std::pair<const uint256, CBlockIndex *> &it : | for (const std::pair<const BlockHash, CBlockIndex *> &it : | ||||
mapBlockIndex) { | mapBlockIndex) { | ||||
delete it.second; | delete it.second; | ||||
} | } | ||||
mapBlockIndex.clear(); | mapBlockIndex.clear(); | ||||
} | } | ||||
} instance_of_cmaincleanup; | } instance_of_cmaincleanup; |