diff --git a/src/chain.h b/src/chain.h --- a/src/chain.h +++ b/src/chain.h @@ -177,6 +177,16 @@ BlockHash GetBlockHash() const { 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 { return int64_t(nTime); } int64_t GetBlockTimeMax() const { return int64_t(nTimeMax); } diff --git a/src/net_processing.cpp b/src/net_processing.cpp --- a/src/net_processing.cpp +++ b/src/net_processing.cpp @@ -772,7 +772,7 @@ return; } if (pindex->nStatus.hasData() || chainActive.Contains(pindex)) { - if (pindex->nChainTx) { + if (pindex->HaveTxsDownloaded()) { state->pindexLastCommonBlock = pindex; } } else if (mapBlocksInFlight.count(pindex->GetBlockHash()) == 0) { @@ -1490,7 +1490,8 @@ LOCK(cs_main); const CBlockIndex *pindex = LookupBlockIndex(hash); if (pindex) { - if (pindex->nChainTx && !pindex->IsValid(BlockValidity::SCRIPTS) && + if (pindex->HaveTxsDownloaded() && + !pindex->IsValid(BlockValidity::SCRIPTS) && pindex->IsValid(BlockValidity::TREE)) { // 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 diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp --- a/src/rpc/blockchain.cpp +++ b/src/rpc/blockchain.cpp @@ -1463,7 +1463,7 @@ } else if (block->nStatus.isOnParkedChain()) { // This block or one of its ancestors is parked. status = "parked"; - } 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. status = "headers-only"; diff --git a/src/validation.cpp b/src/validation.cpp --- a/src/validation.cpp +++ b/src/validation.cpp @@ -2624,7 +2624,7 @@ CBlockIndex *pindexTest = pindexNew; bool hasValidAncestor = true; while (hasValidAncestor && pindexTest && pindexTest != pindexFork) { - assert(pindexTest->nChainTx || pindexTest->nHeight == 0); + assert(pindexTest->HaveTxsDownloaded() || pindexTest->nHeight == 0); // If this is a parked chain, but it has enough PoW, clear the park // state. @@ -3054,7 +3054,8 @@ UnparkBlock(pindex); // Make sure it is added to the candidate list if appropriate. - if (pindex->IsValid(BlockValidity::TRANSACTIONS) && pindex->nChainTx) { + if (pindex->IsValid(BlockValidity::TRANSACTIONS) && + pindex->HaveTxsDownloaded()) { setBlockIndexCandidates.insert(pindex); PruneBlockIndexCandidates(); } @@ -3120,7 +3121,7 @@ // so add it again. for (const std::pair &it : mapBlockIndex) { CBlockIndex *i = it.second; - if (i->IsValid(BlockValidity::TRANSACTIONS) && i->nChainTx && + if (i->IsValid(BlockValidity::TRANSACTIONS) && i->HaveTxsDownloaded() && !setBlockIndexCandidates.value_comp()(i, chainActive.Tip())) { setBlockIndexCandidates.insert(i); } @@ -3183,7 +3184,8 @@ m_failed_blocks.erase(pindex); } - if (pindex->IsValid(BlockValidity::TRANSACTIONS) && pindex->nChainTx && + if (pindex->IsValid(BlockValidity::TRANSACTIONS) && + pindex->HaveTxsDownloaded() && setBlockIndexCandidates.value_comp()(chainActive.Tip(), pindex)) { setBlockIndexCandidates.insert(pindex); } @@ -3349,7 +3351,7 @@ pindexNew->RaiseValidity(BlockValidity::TRANSACTIONS); 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. std::deque queue; @@ -4493,7 +4495,7 @@ // at some point. Pruned nodes may have deleted the block. if (pindex->nTx > 0) { if (pindex->pprev) { - if (pindex->pprev->nChainTx) { + if (pindex->pprev->HaveTxsDownloaded()) { pindex->nChainTx = pindex->pprev->nChainTx + pindex->nTx; } else { pindex->nChainTx = 0; @@ -4511,7 +4513,7 @@ setDirtyBlockIndex.insert(pindex); } if (pindex->IsValid(BlockValidity::TRANSACTIONS) && - (pindex->nChainTx || pindex->pprev == nullptr)) { + (pindex->HaveTxsDownloaded() || pindex->pprev == nullptr)) { setBlockIndexCandidates.insert(pindex); } @@ -4980,7 +4982,7 @@ for (const auto &entry : mapBlockIndex) { CBlockIndex *pindexIter = entry.second; if (pindexIter->IsValid(BlockValidity::TRANSACTIONS) && - pindexIter->nChainTx) { + pindexIter->HaveTxsDownloaded()) { setBlockIndexCandidates.insert(pindexIter); } } @@ -5373,7 +5375,7 @@ // The current active chain's genesis block must be this block. assert(pindex == chainActive.Genesis()); } - if (pindex->nChainTx == 0) { + if (!pindex->HaveTxsDownloaded()) { // nSequenceId can't be set positive for blocks that aren't linked // (negative is used for preciousblock) assert(pindex->nSequenceId <= 0); @@ -5398,14 +5400,14 @@ assert((pindex->nStatus.getValidity() >= BlockValidity::TRANSACTIONS) == (pindex->nTx > 0)); // All parents having had data (at some point) is equivalent to all - // parents being VALID_TRANSACTIONS, which is equivalent to nChainTx - // being set. - // nChainTx != 0 is used to signal that all parent blocks have been - // processed (but may have been pruned). - assert((pindexFirstNeverProcessed != nullptr) == - (pindex->nChainTx == 0)); - assert((pindexFirstNotTransactionsValid != nullptr) == - (pindex->nChainTx == 0)); + // parents being VALID_TRANSACTIONS, which is equivalent to + // HaveTxsDownloaded(). 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->HaveTxsDownloaded())); + assert((pindexFirstNotTransactionsValid == nullptr) == + (pindex->HaveTxsDownloaded())); // nHeight must be consistent. assert(pindex->nHeight == nHeight); // For every block except the genesis block, the chainwork must be