validation: Add and use HaveTxsDownloaded where appropriate

pull/643/head
MarcoFalke 6 years ago
parent ed12fd83ca
commit fa4fc8856b
No known key found for this signature in database
GPG Key ID: CE2B75697E69A548

@ -294,6 +294,15 @@ public:
return *phashBlock; return *phashBlock;
} }
/**
* Check whether this block's and all previous blocks' transactions have been
* downloaded (and stored to disk) at some point.
*
* Does not imply the transactions are consensus-valid (ConnectTip might fail)
* Does not imply the transactions are still stored on disk. (IsBlockPruned might return true)
*/
bool HaveTxsDownloaded() const { return nChainTx != 0; }
int64_t GetBlockTime() const int64_t GetBlockTime() const
{ {
return (int64_t)nTime; return (int64_t)nTime;

@ -566,7 +566,7 @@ static void FindNextBlocksToDownload(NodeId nodeid, unsigned int count, std::vec
return; return;
} }
if (pindex->nStatus & BLOCK_HAVE_DATA || chainActive.Contains(pindex)) { if (pindex->nStatus & BLOCK_HAVE_DATA || chainActive.Contains(pindex)) {
if (pindex->nChainTx) if (pindex->HaveTxsDownloaded())
state->pindexLastCommonBlock = pindex; state->pindexLastCommonBlock = pindex;
} else if (mapBlocksInFlight.count(pindex->GetBlockHash()) == 0) { } else if (mapBlocksInFlight.count(pindex->GetBlockHash()) == 0) {
// The block is not already downloaded, and not yet in flight. // The block is not already downloaded, and not yet in flight.
@ -1124,7 +1124,7 @@ void static ProcessGetBlockData(CNode* pfrom, const CChainParams& chainparams, c
LOCK(cs_main); LOCK(cs_main);
const CBlockIndex* pindex = LookupBlockIndex(inv.hash); const CBlockIndex* pindex = LookupBlockIndex(inv.hash);
if (pindex) { if (pindex) {
if (pindex->nChainTx && !pindex->IsValid(BLOCK_VALID_SCRIPTS) && if (pindex->HaveTxsDownloaded() && !pindex->IsValid(BLOCK_VALID_SCRIPTS) &&
pindex->IsValid(BLOCK_VALID_TREE)) { pindex->IsValid(BLOCK_VALID_TREE)) {
// If we have the block and all of its parents, but have not yet validated it, // If we have the block and all of its parents, but have not yet validated it,
// we might be in the middle of connecting it (ie in the unlock of cs_main // we might be in the middle of connecting it (ie in the unlock of cs_main

@ -1458,7 +1458,7 @@ static UniValue getchaintips(const JSONRPCRequest& request)
} else if (block->nStatus & BLOCK_FAILED_MASK) { } else if (block->nStatus & BLOCK_FAILED_MASK) {
// This block or one of its ancestors is invalid. // This block or one of its ancestors is invalid.
status = "invalid"; status = "invalid";
} else if (block->nChainTx == 0) { } else if (!block->HaveTxsDownloaded()) {
// This block cannot be connected because full block data for it or one of its parents is missing. // This block cannot be connected because full block data for it or one of its parents is missing.
status = "headers-only"; status = "headers-only";
} else if (block->IsValid(BLOCK_VALID_SCRIPTS)) { } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) {

@ -2487,7 +2487,7 @@ CBlockIndex* CChainState::FindMostWorkChain() {
CBlockIndex *pindexTest = pindexNew; CBlockIndex *pindexTest = pindexNew;
bool fInvalidAncestor = false; bool fInvalidAncestor = false;
while (pindexTest && !chainActive.Contains(pindexTest)) { while (pindexTest && !chainActive.Contains(pindexTest)) {
assert(pindexTest->nChainTx || pindexTest->nHeight == 0); assert(pindexTest->HaveTxsDownloaded() || pindexTest->nHeight == 0);
// Pruned nodes may have entries in setBlockIndexCandidates for // Pruned nodes may have entries in setBlockIndexCandidates for
// which block files have been deleted. Remove those as candidates // which block files have been deleted. Remove those as candidates
@ -2777,7 +2777,7 @@ bool CChainState::PreciousBlock(CValidationState& state, const CChainParams& par
// call preciousblock 2**31-1 times on the same set of tips... // call preciousblock 2**31-1 times on the same set of tips...
nBlockReverseSequenceId--; nBlockReverseSequenceId--;
} }
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && pindex->nChainTx) { if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && pindex->HaveTxsDownloaded()) {
setBlockIndexCandidates.insert(pindex); setBlockIndexCandidates.insert(pindex);
PruneBlockIndexCandidates(); PruneBlockIndexCandidates();
} }
@ -2838,7 +2838,7 @@ bool CChainState::InvalidateBlock(CValidationState& state, const CChainParams& c
// add it again. // add it again.
BlockMap::iterator it = mapBlockIndex.begin(); BlockMap::iterator it = mapBlockIndex.begin();
while (it != mapBlockIndex.end()) { while (it != mapBlockIndex.end()) {
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && !setBlockIndexCandidates.value_comp()(it->second, chainActive.Tip())) { if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->HaveTxsDownloaded() && !setBlockIndexCandidates.value_comp()(it->second, chainActive.Tip())) {
setBlockIndexCandidates.insert(it->second); setBlockIndexCandidates.insert(it->second);
} }
it++; it++;
@ -2868,7 +2868,7 @@ void CChainState::ResetBlockFailureFlags(CBlockIndex *pindex) {
if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) { if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) {
it->second->nStatus &= ~BLOCK_FAILED_MASK; it->second->nStatus &= ~BLOCK_FAILED_MASK;
setDirtyBlockIndex.insert(it->second); setDirtyBlockIndex.insert(it->second);
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) { if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->HaveTxsDownloaded() && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) {
setBlockIndexCandidates.insert(it->second); setBlockIndexCandidates.insert(it->second);
} }
if (it->second == pindexBestInvalid) { if (it->second == pindexBestInvalid) {
@ -2946,7 +2946,7 @@ void CChainState::ReceivedBlockTransactions(const CBlock& block, CBlockIndex* pi
pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS); pindexNew->RaiseValidity(BLOCK_VALID_TRANSACTIONS);
setDirtyBlockIndex.insert(pindexNew); setDirtyBlockIndex.insert(pindexNew);
if (pindexNew->pprev == nullptr || pindexNew->pprev->nChainTx) { if (pindexNew->pprev == nullptr || pindexNew->pprev->HaveTxsDownloaded()) {
// If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS. // If pindexNew is the genesis block or all parents are BLOCK_VALID_TRANSACTIONS.
std::deque<CBlockIndex*> queue; std::deque<CBlockIndex*> queue;
queue.push_back(pindexNew); queue.push_back(pindexNew);
@ -3839,7 +3839,7 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
// Pruned nodes may have deleted the block. // Pruned nodes may have deleted the block.
if (pindex->nTx > 0) { if (pindex->nTx > 0) {
if (pindex->pprev) { if (pindex->pprev) {
if (pindex->pprev->nChainTx) { if (pindex->pprev->HaveTxsDownloaded()) {
pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx; pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx;
} else { } else {
pindex->nChainTx = 0; pindex->nChainTx = 0;
@ -3853,7 +3853,7 @@ bool CChainState::LoadBlockIndex(const Consensus::Params& consensus_params, CBlo
pindex->nStatus |= BLOCK_FAILED_CHILD; pindex->nStatus |= BLOCK_FAILED_CHILD;
setDirtyBlockIndex.insert(pindex); setDirtyBlockIndex.insert(pindex);
} }
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->nChainTx || pindex->pprev == nullptr)) if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && (pindex->HaveTxsDownloaded() || pindex->pprev == nullptr))
setBlockIndexCandidates.insert(pindex); setBlockIndexCandidates.insert(pindex);
if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork)) if (pindex->nStatus & BLOCK_FAILED_MASK && (!pindexBestInvalid || pindex->nChainWork > pindexBestInvalid->nChainWork))
pindexBestInvalid = pindex; pindexBestInvalid = pindex;
@ -4222,7 +4222,7 @@ bool CChainState::RewindBlockIndex(const CChainParams& params)
++ret.first; ++ret.first;
} }
} }
} else if (pindexIter->IsValid(BLOCK_VALID_TRANSACTIONS) && pindexIter->nChainTx) { } else if (pindexIter->IsValid(BLOCK_VALID_TRANSACTIONS) && pindexIter->HaveTxsDownloaded()) {
setBlockIndexCandidates.insert(pindexIter); setBlockIndexCandidates.insert(pindexIter);
} }
} }
@ -4523,7 +4523,7 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
assert(pindex->GetBlockHash() == consensusParams.hashGenesisBlock); // Genesis block's hash must match. assert(pindex->GetBlockHash() == consensusParams.hashGenesisBlock); // Genesis block's hash must match.
assert(pindex == chainActive.Genesis()); // The current active chain's genesis block must be this block. assert(pindex == chainActive.Genesis()); // The current active chain's genesis block must be this block.
} }
if (pindex->nChainTx == 0) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock) if (!pindex->HaveTxsDownloaded()) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock)
// VALID_TRANSACTIONS is equivalent to nTx > 0 for all nodes (whether or not pruning has occurred). // VALID_TRANSACTIONS is equivalent to nTx > 0 for all nodes (whether or not pruning has occurred).
// HAVE_DATA is only equivalent to nTx > 0 (or VALID_TRANSACTIONS) if no pruning has occurred. // HAVE_DATA is only equivalent to nTx > 0 (or VALID_TRANSACTIONS) if no pruning has occurred.
if (!fHavePruned) { if (!fHavePruned) {
@ -4536,9 +4536,9 @@ void CChainState::CheckBlockIndex(const Consensus::Params& consensusParams)
} }
if (pindex->nStatus & BLOCK_HAVE_UNDO) assert(pindex->nStatus & BLOCK_HAVE_DATA); if (pindex->nStatus & BLOCK_HAVE_UNDO) assert(pindex->nStatus & BLOCK_HAVE_DATA);
assert(((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS) == (pindex->nTx > 0)); // This is pruning-independent. assert(((pindex->nStatus & BLOCK_VALID_MASK) >= BLOCK_VALID_TRANSACTIONS) == (pindex->nTx > 0)); // This is pruning-independent.
// All parents having had data (at some point) is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to nChainTx being set. // All parents having had data (at some point) is equivalent to all parents being VALID_TRANSACTIONS, which is equivalent to HaveTxsDownloaded().
assert((pindexFirstNeverProcessed != nullptr) == (pindex->nChainTx == 0)); // nChainTx != 0 is used to signal that all parent blocks have been processed (but may have been pruned). assert((pindexFirstNeverProcessed == nullptr) == pindex->HaveTxsDownloaded());
assert((pindexFirstNotTransactionsValid != nullptr) == (pindex->nChainTx == 0)); assert((pindexFirstNotTransactionsValid == nullptr) == pindex->HaveTxsDownloaded());
assert(pindex->nHeight == nHeight); // nHeight must be consistent. assert(pindex->nHeight == nHeight); // nHeight must be consistent.
assert(pindex->pprev == nullptr || pindex->nChainWork >= pindex->pprev->nChainWork); // For every block except the genesis block, the chainwork must be larger than the parent's. assert(pindex->pprev == nullptr || pindex->nChainWork >= pindex->pprev->nChainWork); // For every block except the genesis block, the chainwork must be larger than the parent's.
assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight))); // The pskip pointer must point back for all but the first 2 blocks. assert(nHeight < 2 || (pindex->pskip && (pindex->pskip->nHeight < nHeight))); // The pskip pointer must point back for all but the first 2 blocks.

Loading…
Cancel
Save