aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWladimir J. van der Laan <[email protected]>2017-01-11 14:16:11 +0100
committerWladimir J. van der Laan <[email protected]>2017-01-11 14:26:00 +0100
commite2e624d9ce54d5d0f1fc0b1934c798804d7d7cff (patch)
tree609be91bd4d9b67b812b75a5bf1b50a2aeabf7c2 /src
parentMerge #9471: [depends] libevent 2.1.7rc (diff)
parentfixup! Add pruneblockchain RPC to enable manual block file pruning. (diff)
downloaddiscoin-e2e624d9ce54d5d0f1fc0b1934c798804d7d7cff.tar.xz
discoin-e2e624d9ce54d5d0f1fc0b1934c798804d7d7cff.zip
Merge #7871: Manual block file pruning.
afffeea fixup! Add pruneblockchain RPC to enable manual block file pruning. (Russell Yanofsky) 1fc4ec7 Add pruneblockchain RPC to enable manual block file pruning. (mrbandrews)
Diffstat (limited to 'src')
-rw-r--r--src/init.cpp16
-rw-r--r--src/rpc/blockchain.cpp41
-rw-r--r--src/rpc/client.cpp1
-rw-r--r--src/validation.cpp44
-rw-r--r--src/validation.h2
5 files changed, 93 insertions, 11 deletions
diff --git a/src/init.cpp b/src/init.cpp
index 992ce8ebd..9ac69b7d3 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -351,9 +351,9 @@ std::string HelpMessage(HelpMessageMode mode)
#ifndef WIN32
strUsage += HelpMessageOpt("-pid=<file>", strprintf(_("Specify pid file (default: %s)"), BITCOIN_PID_FILENAME));
#endif
- strUsage += HelpMessageOpt("-prune=<n>", strprintf(_("Reduce storage requirements by pruning (deleting) old blocks. This mode is incompatible with -txindex and -rescan. "
+ strUsage += HelpMessageOpt("-prune=<n>", strprintf(_("Reduce storage requirements by enabling pruning (deleting) of old blocks. This allows the pruneblockchain RPC to be called to delete specific blocks, and enables automatic pruning of old blocks if a target size in MiB is provided. This mode is incompatible with -txindex and -rescan. "
"Warning: Reverting this setting requires re-downloading the entire blockchain. "
- "(default: 0 = disable pruning blocks, >%u = target size in MiB to use for block files)"), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024));
+ "(default: 0 = disable pruning blocks, 1 = allow manual pruning via RPC, >%u = automatically prune block files to stay under the specified target size in MiB)"), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024));
strUsage += HelpMessageOpt("-reindex-chainstate", _("Rebuild chain state from the currently indexed blocks"));
strUsage += HelpMessageOpt("-reindex", _("Rebuild chain state and block index from the blk*.dat files on disk"));
#ifndef WIN32
@@ -936,12 +936,16 @@ bool AppInitParameterInteraction()
nScriptCheckThreads = MAX_SCRIPTCHECK_THREADS;
// block pruning; get the amount of disk space (in MiB) to allot for block & undo files
- int64_t nSignedPruneTarget = GetArg("-prune", 0) * 1024 * 1024;
- if (nSignedPruneTarget < 0) {
+ int64_t nPruneArg = GetArg("-prune", 0);
+ if (nPruneArg < 0) {
return InitError(_("Prune cannot be configured with a negative value."));
}
- nPruneTarget = (uint64_t) nSignedPruneTarget;
- if (nPruneTarget) {
+ nPruneTarget = (uint64_t) nPruneArg * 1024 * 1024;
+ if (nPruneArg == 1) { // manual pruning: -prune=1
+ LogPrintf("Block pruning enabled. Use RPC call pruneblockchain(height) to manually prune block and undo files.\n");
+ nPruneTarget = std::numeric_limits<uint64_t>::max();
+ fPruneMode = true;
+ } else if (nPruneTarget) {
if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) {
return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024));
}
diff --git a/src/rpc/blockchain.cpp b/src/rpc/blockchain.cpp
index 0b42c1d62..e828618a8 100644
--- a/src/rpc/blockchain.cpp
+++ b/src/rpc/blockchain.cpp
@@ -814,6 +814,46 @@ static bool GetUTXOStats(CCoinsView *view, CCoinsStats &stats)
return true;
}
+UniValue pruneblockchain(const JSONRPCRequest& request)
+{
+ if (request.fHelp || request.params.size() != 1)
+ throw runtime_error(
+ "pruneblockchain\n"
+ "\nArguments:\n"
+ "1. \"height\" (numeric, required) The block height to prune up to. May be set to a discrete height, or to a unix timestamp to prune based on block time.\n");
+
+ if (!fPruneMode)
+ throw JSONRPCError(RPC_METHOD_NOT_FOUND, "Cannot prune blocks because node is not in prune mode.");
+
+ LOCK(cs_main);
+
+ int heightParam = request.params[0].get_int();
+ if (heightParam < 0)
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Negative block height.");
+
+ // Height value more than a billion is too high to be a block height, and
+ // too low to be a block time (corresponds to timestamp from Sep 2001).
+ if (heightParam > 1000000000) {
+ CBlockIndex* pindex = chainActive.FindLatestBefore(heightParam);
+ if (!pindex) {
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Could not find block before specified timestamp.");
+ }
+ heightParam = pindex->nHeight;
+ }
+
+ unsigned int height = (unsigned int) heightParam;
+ unsigned int chainHeight = (unsigned int) chainActive.Height();
+ if (chainHeight < Params().PruneAfterHeight())
+ throw JSONRPCError(RPC_INTERNAL_ERROR, "Blockchain is too short for pruning.");
+ else if (height > chainHeight)
+ throw JSONRPCError(RPC_INVALID_PARAMETER, "Blockchain is shorter than the attempted prune height.");
+ else if (height > chainHeight - MIN_BLOCKS_TO_KEEP)
+ LogPrint("rpc", "Attempt to prune blocks close to the tip. Retaining the minimum number of blocks.");
+
+ PruneBlockFilesManual(height);
+ return NullUniValue;
+}
+
UniValue gettxoutsetinfo(const JSONRPCRequest& request)
{
if (request.fHelp || request.params.size() != 0)
@@ -1384,6 +1424,7 @@ static const CRPCCommand commands[] =
{ "blockchain", "getrawmempool", &getrawmempool, true, {"verbose"} },
{ "blockchain", "gettxout", &gettxout, true, {"txid","n","include_mempool"} },
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true, {} },
+ { "blockchain", "pruneblockchain", &pruneblockchain, true, {"height"} },
{ "blockchain", "verifychain", &verifychain, true, {"checklevel","nblocks"} },
{ "blockchain", "preciousblock", &preciousblock, true, {"blockhash"} },
diff --git a/src/rpc/client.cpp b/src/rpc/client.cpp
index 422d005f0..5d3c45845 100644
--- a/src/rpc/client.cpp
+++ b/src/rpc/client.cpp
@@ -103,6 +103,7 @@ static const CRPCConvertParam vRPCConvertParams[] =
{ "importmulti", 1, "options" },
{ "verifychain", 0, "checklevel" },
{ "verifychain", 1, "nblocks" },
+ { "pruneblockchain", 0, "height" },
{ "keypoolrefill", 0, "newsize" },
{ "getrawmempool", 0, "verbose" },
{ "estimatefee", 0, "nblocks" },
diff --git a/src/validation.cpp b/src/validation.cpp
index 37a4186e0..109a71fe7 100644
--- a/src/validation.cpp
+++ b/src/validation.cpp
@@ -185,7 +185,8 @@ enum FlushStateMode {
};
// See definition for documentation
-bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode);
+bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int nManualPruneHeight=0);
+void FindFilesToPruneManual(std::set<int>& setFilesToPrune, int nManualPruneHeight);
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
{
@@ -1934,7 +1935,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
* if they're too large, if it's been a while since the last write,
* or always and in all cases if we're in prune mode and are deleting files.
*/
-bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
+bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode, int nManualPruneHeight) {
int64_t nMempoolUsage = mempool.DynamicMemoryUsage();
const CChainParams& chainparams = Params();
LOCK2(cs_main, cs_LastBlockFile);
@@ -1944,9 +1945,13 @@ bool static FlushStateToDisk(CValidationState &state, FlushStateMode mode) {
std::set<int> setFilesToPrune;
bool fFlushForPrune = false;
try {
- if (fPruneMode && fCheckForPruning && !fReindex) {
- FindFilesToPrune(setFilesToPrune, chainparams.PruneAfterHeight());
- fCheckForPruning = false;
+ if (fPruneMode && (fCheckForPruning || nManualPruneHeight > 0) && !fReindex) {
+ if (nManualPruneHeight > 0) {
+ FindFilesToPruneManual(setFilesToPrune, nManualPruneHeight);
+ } else {
+ FindFilesToPrune(setFilesToPrune, chainparams.PruneAfterHeight());
+ fCheckForPruning = false;
+ }
if (!setFilesToPrune.empty()) {
fFlushForPrune = true;
if (!fHavePruned) {
@@ -3247,6 +3252,35 @@ void UnlinkPrunedFiles(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)
+{
+ assert(fPruneMode && nManualPruneHeight > 0);
+
+ LOCK2(cs_main, cs_LastBlockFile);
+ if (chainActive.Tip() == NULL)
+ return;
+
+ // last block to prune is the lesser of (user-specified height, MIN_BLOCKS_TO_KEEP from the tip)
+ unsigned int nLastBlockWeCanPrune = 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;
+ FlushStateToDisk(state, FLUSH_STATE_NONE, nManualPruneHeight);
+}
+
/* Calculate the block/rev files that should be deleted to remain under target*/
void FindFilesToPrune(std::set<int>& setFilesToPrune, uint64_t nPruneAfterHeight)
{
diff --git a/src/validation.h b/src/validation.h
index 631602a70..f5e76c7d3 100644
--- a/src/validation.h
+++ b/src/validation.h
@@ -309,6 +309,8 @@ CBlockIndex * InsertBlockIndex(uint256 hash);
void FlushStateToDisk();
/** Prune block files and flush state to disk. */
void PruneAndFlush();
+/** Prune block files up to a given height */
+void PruneBlockFilesManual(int nPruneUpToHeight);
/** (try to) add transaction to memory pool **/
bool AcceptToMemoryPool(CTxMemPool& pool, CValidationState &state, const CTransactionRef &tx, bool fLimitFree,