Skip to content

Commit

Permalink
split validation.cpp into multiple files:
Browse files Browse the repository at this point in the history
    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
Naviabheeman committed May 2, 2024
1 parent c57de8d commit 471d5e2
Show file tree
Hide file tree
Showing 26 changed files with 3,425 additions and 3,237 deletions.
14 changes: 13 additions & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,11 @@ BITCOIN_CORE_H = \
bech32.h \
bloom.h \
blockencodings.h \
blockprune.h \
chain.h \
chainparams.h \
chainparamsseeds.h \
chainstate.h \
checkpoints.h \
checkqueue.h \
clientversion.h \
Expand All @@ -106,12 +108,15 @@ BITCOIN_CORE_H = \
compat/endian.h \
compat/sanity.h \
compressor.h \
connecttrace.h \
consensus/consensus.h \
consensus/tx_verify.h \
core_io.h \
core_memusage.h \
cs_main.h \
cuckoocache.h \
federationparams.h \
file_io.h \
fs.h \
httprpc.h \
httpserver.h \
Expand Down Expand Up @@ -157,6 +162,7 @@ BITCOIN_CORE_H = \
rpc/register.h \
rpc/util.h \
scheduler.h \
scriptcheck.h \
script/descriptor.h \
script/ismine.h \
script/sigcache.h \
Expand All @@ -175,6 +181,7 @@ BITCOIN_CORE_H = \
threadinterrupt.h \
timedata.h \
torcontrol.h \
trace.h \
txdb.h \
txmempool.h \
ui_interface.h \
Expand All @@ -197,8 +204,8 @@ BITCOIN_CORE_H = \
wallet/walletutil.h \
wallet/coinselection.h \
warnings.h \
verifydb.h \
xfieldhistory.h \
trace.h \
zmq/zmqabstractnotifier.h \
zmq/zmqconfig.h\
zmq/zmqnotificationinterface.h \
Expand All @@ -220,9 +227,13 @@ libtapyrus_server_a_SOURCES = \
addrman.cpp \
bloom.cpp \
blockencodings.cpp \
blockprune.cpp \
chain.cpp \
chainstate.cpp \
checkpoints.cpp \
consensus/tx_verify.cpp \
cs_main.cpp \
file_io.cpp \
httprpc.cpp \
httpserver.cpp \
index/base.cpp \
Expand Down Expand Up @@ -255,6 +266,7 @@ libtapyrus_server_a_SOURCES = \
txmempool.cpp \
ui_interface.cpp \
validation.cpp \
verifydb.cpp \
validationinterface.cpp \
$(BITCOIN_CORE_H)

Expand Down
167 changes: 167 additions & 0 deletions src/blockprune.cpp
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;
}
48 changes: 48 additions & 0 deletions src/blockprune.h
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
Loading

0 comments on commit 471d5e2

Please sign in to comment.