-
Notifications
You must be signed in to change notification settings - Fork 17
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
split validation.cpp into multiple files:
validation.cpp - only transaction and block validation code verifydb.cpp - veridydb class chainstate.cpp - chainstate class and other helper code used in it cs_main.cpp - common critical sections file_io.cpp - all disk read and write operations blockprune.cpp - blockprune class
- Loading branch information
1 parent
c57de8d
commit 471d5e2
Showing
26 changed files
with
3,425 additions
and
3,237 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
// Copyright (c) 2024 Chaintope Inc. | ||
// Distributed under the MIT software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
#include <validation.h> | ||
#include <cs_main.h> | ||
#include <blockprune.h> | ||
#include <file_io.h> | ||
|
||
|
||
/** | ||
* BLOCK PRUNING CODE | ||
*/ | ||
|
||
/* Calculate the amount of disk space the block & undo files currently use */ | ||
uint64_t CalculateCurrentUsage() | ||
{ | ||
LOCK(cs_LastBlockFile); | ||
|
||
uint64_t retval = 0; | ||
for (const CBlockFileInfo &file : vinfoBlockFile) { | ||
retval += file.nSize + file.nUndoSize; | ||
} | ||
return retval; | ||
} | ||
|
||
/* Prune a block file (modify associated database entries)*/ | ||
void PruneOneBlockFile(const int fileNumber) | ||
{ | ||
LOCK(cs_LastBlockFile); | ||
|
||
for (const auto& entry : mapBlockIndex) { | ||
CBlockIndex* pindex = entry.second; | ||
if (pindex->nFile == fileNumber) { | ||
pindex->nStatus &= ~BLOCK_HAVE_DATA; | ||
pindex->nStatus &= ~BLOCK_HAVE_UNDO; | ||
pindex->nFile = 0; | ||
pindex->nDataPos = 0; | ||
pindex->nUndoPos = 0; | ||
setDirtyBlockIndex.insert(pindex); | ||
|
||
// Prune from mapBlocksUnlinked -- any block we prune would have | ||
// to be downloaded again in order to consider its chain, at which | ||
// point it would be considered as a candidate for | ||
// mapBlocksUnlinked or setBlockIndexCandidates. | ||
std::pair<std::multimap<CBlockIndex*, CBlockIndex*>::iterator, std::multimap<CBlockIndex*, CBlockIndex*>::iterator> range = mapBlocksUnlinked.equal_range(pindex->pprev); | ||
while (range.first != range.second) { | ||
std::multimap<CBlockIndex *, CBlockIndex *>::iterator _it = range.first; | ||
range.first++; | ||
if (_it->second == pindex) { | ||
mapBlocksUnlinked.erase(_it); | ||
} | ||
} | ||
} | ||
} | ||
|
||
vinfoBlockFile[fileNumber].SetNull(); | ||
setDirtyFileInfo.insert(fileNumber); | ||
} | ||
|
||
|
||
void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune) | ||
{ | ||
for (std::set<int>::iterator it = setFilesToPrune.begin(); it != setFilesToPrune.end(); ++it) { | ||
CDiskBlockPos pos(*it, 0); | ||
fs::remove(GetBlockPosFilename(pos, "blk")); | ||
fs::remove(GetBlockPosFilename(pos, "rev")); | ||
LogPrintf("Prune: %s deleted blk/rev (%05u)\n", __func__, *it); | ||
} | ||
} | ||
|
||
void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight) | ||
{ | ||
assert(fPruneMode && nManualPruneHeight > 0); | ||
|
||
LOCK2(cs_main, cs_LastBlockFile); | ||
if (chainActive.Tip() == nullptr) | ||
return; | ||
|
||
// last block to prune is the lesser of (user-specified height, MIN_BLOCKS_TO_KEEP from the tip) | ||
unsigned int nLastBlockWeCanPrune = std::min((unsigned)nManualPruneHeight, chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP); | ||
int count=0; | ||
for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) { | ||
if (vinfoBlockFile[fileNumber].nSize == 0 || vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune) | ||
continue; | ||
PruneOneBlockFile(fileNumber); | ||
setFilesToPrune.insert(fileNumber); | ||
count++; | ||
} | ||
LogPrintf("Prune (Manual): prune_height=%d removed %d blk/rev pairs\n", nLastBlockWeCanPrune, count); | ||
} | ||
|
||
/* This function is called from the RPC code for pruneblockchain */ | ||
void PruneBlockFilesManual(int nManualPruneHeight) | ||
{ | ||
CValidationState state; | ||
if (!FlushStateToDisk(state, FlushStateMode::NONE, nManualPruneHeight)) { | ||
LogPrintf("%s: failed to flush state (%s)\n", __func__, FormatStateMessage(state)); | ||
} | ||
} | ||
|
||
void FindFilesToPrune(std::set<int>& setFilesToPrune, uint32_t nPruneAfterHeight) | ||
{ | ||
LOCK2(cs_main, cs_LastBlockFile); | ||
if (chainActive.Tip() == nullptr || nPruneTarget == 0) { | ||
return; | ||
} | ||
if (chainActive.Tip()->nHeight <= nPruneAfterHeight) { | ||
return; | ||
} | ||
|
||
unsigned int nLastBlockWeCanPrune = chainActive.Tip()->nHeight - MIN_BLOCKS_TO_KEEP; | ||
uint64_t nCurrentUsage = CalculateCurrentUsage(); | ||
// 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 allocation | ||
// before the next pruning. | ||
uint64_t nBuffer = BLOCKFILE_CHUNK_SIZE + UNDOFILE_CHUNK_SIZE; | ||
uint64_t nBytesToPrune; | ||
int count=0; | ||
|
||
if (nCurrentUsage + nBuffer >= nPruneTarget) { | ||
// On a prune event, the chainstate DB is flushed. | ||
// To avoid excessive prune events negating the benefit of high dbcache | ||
// values, we should not prune too rapidly. | ||
// So when pruning in IBD, increase the buffer a bit to avoid a re-prune too soon. | ||
if (IsInitialBlockDownload()) { | ||
// Since this is only relevant during IBD, we use a fixed 10% | ||
nBuffer += nPruneTarget / 10; | ||
} | ||
|
||
for (int fileNumber = 0; fileNumber < nLastBlockFile; fileNumber++) { | ||
nBytesToPrune = vinfoBlockFile[fileNumber].nSize + vinfoBlockFile[fileNumber].nUndoSize; | ||
|
||
if (vinfoBlockFile[fileNumber].nSize == 0) | ||
continue; | ||
|
||
if (nCurrentUsage + nBuffer < nPruneTarget) // are we below our target? | ||
break; | ||
|
||
// don't prune files that could have a block within MIN_BLOCKS_TO_KEEP of the prod chain's tip but keep scanning | ||
if (vinfoBlockFile[fileNumber].nHeightLast > nLastBlockWeCanPrune) | ||
continue; | ||
|
||
PruneOneBlockFile(fileNumber); | ||
// Queue up the files for removal | ||
setFilesToPrune.insert(fileNumber); | ||
nCurrentUsage -= nBytesToPrune; | ||
count++; | ||
} | ||
} | ||
|
||
LogPrint(BCLog::PRUNE, "Prune: target=%dMiB actual=%dMiB diff=%dMiB max_prune_height=%d removed %d blk/rev pairs\n", | ||
nPruneTarget/1024/1024, nCurrentUsage/1024/1024, | ||
((int64_t)nPruneTarget - (int64_t)nCurrentUsage)/1024/1024, | ||
nLastBlockWeCanPrune, count); | ||
} | ||
|
||
bool CheckDiskSpace(uint64_t nAdditionalBytes, bool blocks_dir) | ||
{ | ||
uint64_t nFreeBytesAvailable = fs::space(blocks_dir ? GetBlocksDir() : GetDataDir()).available; | ||
|
||
// Check for nMinDiskSpace bytes (currently 50MB) | ||
if (nFreeBytesAvailable < nMinDiskSpace + nAdditionalBytes) | ||
return AbortNode("Disk space is low!", _("Error: Disk space is low!")); | ||
|
||
return true; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
// Copyright (c) 2023 The Bitcoin Core developers | ||
// Copyright (c) 2024 Chaintope Inc. | ||
// Distributed under the MIT software license, see the accompanying | ||
// file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||
|
||
#ifndef BITCOIN_BLOCK_PRUNE_H | ||
#define BITCOIN_BLOCK_PRUNE_H | ||
|
||
/** Minimum disk space required - used in CheckDiskSpace() */ | ||
static const uint64_t nMinDiskSpace = 52428800; | ||
|
||
/** Check whether enough disk space is available for an incoming block */ | ||
bool CheckDiskSpace(uint64_t nAdditionalBytes = 0, bool blocks_dir = false); | ||
|
||
/** Calculate the amount of disk space the block & undo files currently use */ | ||
uint64_t CalculateCurrentUsage(); | ||
|
||
/** | ||
* Mark one block file as pruned. | ||
*/ | ||
void PruneOneBlockFile(const int fileNumber); | ||
|
||
/** | ||
* Actually unlink the specified files | ||
*/ | ||
void UnlinkPrunedFiles(const std::set<int>& setFilesToPrune); | ||
|
||
/* Calculate the block/rev files to delete based on height specified by user with RPC command pruneblockchain */ | ||
void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight); | ||
|
||
/** | ||
* Prune block and undo files (blk???.dat and undo???.dat) so that the disk space used is less than a user-defined target. | ||
* The user sets the target (in MB) on the command line or in config file. This will be run on startup and whenever new | ||
* space is allocated in a block or undo file, staying below the target. Changing back to unpruned requires a reindex | ||
* (which in this case means the blockchain must be re-downloaded.) | ||
* | ||
* Pruning functions are called from FlushStateToDisk when the global fCheckForPruning flag has been set. | ||
* Block and undo files are deleted in lock-step (when blk00003.dat is deleted, so is rev00003.dat.) | ||
* Pruning cannot take place until the longest chain is at least a certain length (100000 on mainnet, 1000 on testnet, 1000 on dev). | ||
* Pruning will never delete a block within a defined distance (currently 288) from the active chain's tip. | ||
* The block index is updated by unsetting HAVE_DATA and HAVE_UNDO for any blocks that were stored in the deleted files. | ||
* A db flag records the fact that at least some block files have been pruned. | ||
* | ||
* @param[out] setFilesToPrune The set of file indices that can be unlinked will be returned | ||
*/ | ||
void FindFilesToPrune(std::set<int>& setFilesToPrune, uint32_t nPruneAfterHeight); | ||
|
||
#endif // BITCOIN_BLOCK_PRUNE_H |
Oops, something went wrong.