Skip to content

Commit eff6be3

Browse files
committed
Trim headers when loading block index from disk.
1 parent 7c55557 commit eff6be3

File tree

3 files changed

+70
-13
lines changed

3 files changed

+70
-13
lines changed

src/txdb.cpp

Lines changed: 55 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -307,12 +307,47 @@ bool CBlockTreeDB::WritePAKList(const std::vector<std::vector<unsigned char> >&
307307
return Write(std::make_pair(DB_PAK, uint256S("1")), offline_list) && Write(std::make_pair(DB_PAK, uint256S("2")), online_list) && Write(std::make_pair(DB_PAK, uint256S("3")), reject);
308308
}
309309

310-
bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex)
310+
bool CBlockTreeDB::WalkBlockIndexGutsForMaxHeight(int* nHeight) {
311+
std::unique_ptr<CDBIterator> pcursor(NewIterator());
312+
*nHeight = 0;
313+
int i = 0;
314+
pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256()));
315+
while (pcursor->Valid()) {
316+
if (ShutdownRequested()) return false;
317+
std::pair<uint8_t, uint256> key;
318+
if (pcursor->GetKey(key) && key.first == DB_BLOCK_INDEX) {
319+
i++;
320+
if (i > 10'000) {
321+
// Under the (accurate) assumption hat the headers on disk are effectively in random height order,
322+
// we have a good-enough (conservative) estimate of the max height very quickly, and don't need to
323+
// waste more time. Shortcutting like this will cause us to keep a few extra headers, which is fine.
324+
break;
325+
}
326+
CDiskBlockIndex diskindex;
327+
if (pcursor->GetValue(diskindex)) {
328+
if (diskindex.nHeight > *nHeight) {
329+
*nHeight = diskindex.nHeight;
330+
}
331+
pcursor->Next();
332+
} else {
333+
return error("%s: failed to read value", __func__);
334+
}
335+
} else {
336+
break;
337+
}
338+
}
339+
return true;
340+
}
341+
342+
bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex, int trim_below_height)
311343
{
312344
std::unique_ptr<CDBIterator> pcursor(NewIterator());
313345

314346
pcursor->Seek(std::make_pair(DB_BLOCK_INDEX, uint256()));
315347

348+
int n_untrimmed = 0;
349+
int n_total = 0;
350+
316351
// Load m_block_index
317352
while (pcursor->Valid()) {
318353
if (ShutdownRequested()) return false;
@@ -332,19 +367,27 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams,
332367
pindexNew->nTime = diskindex.nTime;
333368
pindexNew->nBits = diskindex.nBits;
334369
pindexNew->nNonce = diskindex.nNonce;
335-
pindexNew->proof = diskindex.proof;
336370
pindexNew->nStatus = diskindex.nStatus;
337371
pindexNew->nTx = diskindex.nTx;
338-
pindexNew->m_dynafed_params = diskindex.m_dynafed_params;
339-
pindexNew->m_signblock_witness = diskindex.m_signblock_witness;
340-
341-
const uint256 block_hash = pindexNew->GetBlockHash();
342-
// Only validate one of every 1000 block header for sanity check
343-
if (pindexNew->nHeight % 1000 == 0 &&
344-
block_hash != consensusParams.hashGenesisBlock &&
345-
!CheckProof(pindexNew->GetBlockHeader(), consensusParams)) {
346-
return error("%s: CheckProof: %s, %s", __func__, block_hash.ToString(), pindexNew->ToString());
372+
373+
n_total++;
374+
if (diskindex.nHeight >= trim_below_height) {
375+
n_untrimmed++;
376+
pindexNew->proof = diskindex.proof;
377+
pindexNew->m_dynafed_params = diskindex.m_dynafed_params;
378+
pindexNew->m_signblock_witness = diskindex.m_signblock_witness;
379+
380+
const uint256 block_hash = pindexNew->GetBlockHash();
381+
// Only validate one of every 1000 block header for sanity check
382+
if (pindexNew->nHeight % 1000 == 0 &&
383+
block_hash != consensusParams.hashGenesisBlock &&
384+
!CheckProof(pindexNew->GetBlockHeader(), consensusParams)) {
385+
return error("%s: CheckProof: %s, %s", __func__, block_hash.ToString(), pindexNew->ToString());
386+
}
387+
} else {
388+
pindexNew->m_trimmed = true;
347389
}
390+
348391
pcursor->Next();
349392
} else {
350393
return error("%s: failed to read value", __func__);
@@ -354,6 +397,7 @@ bool CBlockTreeDB::LoadBlockIndexGuts(const Consensus::Params& consensusParams,
354397
}
355398
}
356399

400+
LogPrintf("LoadBlockIndexGuts: loaded %d total / %d untrimmed (fully in-memory) headers\n", n_total, n_untrimmed);
357401
return true;
358402
}
359403

src/txdb.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,8 +85,9 @@ class CBlockTreeDB : public CDBWrapper
8585
void ReadReindexing(bool &fReindexing);
8686
bool WriteFlag(const std::string &name, bool fValue);
8787
bool ReadFlag(const std::string &name, bool &fValue);
88-
bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex);
88+
bool LoadBlockIndexGuts(const Consensus::Params& consensusParams, std::function<CBlockIndex*(const uint256&)> insertBlockIndex, int trim_below_height);
8989
// ELEMENTS:
90+
bool WalkBlockIndexGutsForMaxHeight(int* nHeight);
9091
bool ReadPAKList(std::vector<std::vector<unsigned char> >& offline_list, std::vector<std::vector<unsigned char> >& online_list, bool& reject);
9192
bool WritePAKList(const std::vector<std::vector<unsigned char> >& offline_list, const std::vector<std::vector<unsigned char> >& online_list, bool reject);
9293
};

src/validation.cpp

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4110,7 +4110,19 @@ bool BlockManager::LoadBlockIndex(
41104110
CBlockTreeDB& blocktree,
41114111
std::set<CBlockIndex*, CBlockIndexWorkComparator>& block_index_candidates)
41124112
{
4113-
if (!blocktree.LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }))
4113+
int trim_below_height = 0;
4114+
if (fTrimHeaders) {
4115+
int max_height = 0;
4116+
if (!blocktree.WalkBlockIndexGutsForMaxHeight(&max_height)) {
4117+
LogPrintf("LoadBlockIndex: Somehow failed to WalkBlockIndexGutsForMaxHeight.\n");
4118+
return false;
4119+
}
4120+
4121+
int must_keep_headers = (consensus_params.total_valid_epochs + 2) * consensus_params.dynamic_epoch_length;
4122+
int extra_headers_buffer = consensus_params.dynamic_epoch_length * 2; // XXX arbitrary
4123+
trim_below_height = max_height - must_keep_headers - extra_headers_buffer;
4124+
}
4125+
if (!blocktree.LoadBlockIndexGuts(consensus_params, [this](const uint256& hash) EXCLUSIVE_LOCKS_REQUIRED(cs_main) { return this->InsertBlockIndex(hash); }, trim_below_height))
41144126
return false;
41154127

41164128
// Calculate nChainWork

0 commit comments

Comments
 (0)