aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/init.cpp30
-rw-r--r--src/main.cpp136
-rw-r--r--src/main.h8
-rw-r--r--src/netbase.cpp2
-rw-r--r--src/qt/bitcoinunits.cpp6
-rw-r--r--src/random.h2
-rw-r--r--src/rpcblockchain.cpp76
-rw-r--r--src/rpcserver.cpp8
-rw-r--r--src/rpcserver.h2
9 files changed, 161 insertions, 109 deletions
diff --git a/src/init.cpp b/src/init.cpp
index 63e72c66d2..7b6ebb1b30 100644
--- a/src/init.cpp
+++ b/src/init.cpp
@@ -330,8 +330,6 @@ std::string HelpMessage(HelpMessageMode mode)
strUsage += " -printtoconsole " + _("Send trace/debug info to console instead of debug.log file") + "\n";
if (GetBoolArg("-help-debug", false))
{
- strUsage += " -printblock=<hash> " + _("Print block on startup, if found in block index") + "\n";
- strUsage += " -printblocktree " + strprintf(_("Print block tree on startup (default: %u)"), 0) + "\n";
strUsage += " -printpriority " + strprintf(_("Log transaction priority and fee per kB when mining blocks (default: %u)"), 0) + "\n";
strUsage += " -privdb " + strprintf(_("Sets the DB_PRIVATE flag in the wallet db environment (default: %u)"), 1) + "\n";
strUsage += " -regtest " + _("Enter regression test mode, which uses a special chain in which blocks can be solved instantly.") + "\n";
@@ -1048,34 +1046,6 @@ bool AppInit2(boost::thread_group& threadGroup)
}
LogPrintf(" block index %15dms\n", GetTimeMillis() - nStart);
- if (GetBoolArg("-printblockindex", false) || GetBoolArg("-printblocktree", false))
- {
- PrintBlockTree();
- return false;
- }
-
- if (mapArgs.count("-printblock"))
- {
- string strMatch = mapArgs["-printblock"];
- int nFound = 0;
- for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
- {
- uint256 hash = (*mi).first;
- if (boost::algorithm::starts_with(hash.ToString(), strMatch))
- {
- CBlockIndex* pindex = (*mi).second;
- CBlock block;
- ReadBlockFromDisk(block, pindex);
- block.BuildMerkleTree();
- LogPrintf("%s\n", block.ToString());
- nFound++;
- }
- }
- if (nFound == 0)
- LogPrintf("No blocks matching %s were found\n", strMatch);
- return false;
- }
-
boost::filesystem::path est_path = GetDataDir() / FEE_ESTIMATES_FILENAME;
CAutoFile est_filein(fopen(est_path.string().c_str(), "rb"), SER_DISK, CLIENT_VERSION);
// Allowed to fail as this file IS missing on first startup.
diff --git a/src/main.cpp b/src/main.cpp
index 0a81d0d7b4..0515eeb156 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -2135,6 +2135,73 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) {
return true;
}
+bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
+ AssertLockHeld(cs_main);
+
+ // Mark the block itself as invalid.
+ pindex->nStatus |= BLOCK_FAILED_VALID;
+ setDirtyBlockIndex.insert(pindex);
+ setBlockIndexCandidates.erase(pindex);
+
+ while (chainActive.Contains(pindex)) {
+ CBlockIndex *pindexWalk = chainActive.Tip();
+ pindexWalk->nStatus |= BLOCK_FAILED_CHILD;
+ setDirtyBlockIndex.insert(pindexWalk);
+ setBlockIndexCandidates.erase(pindexWalk);
+ // ActivateBestChain considers blocks already in chainActive
+ // unconditionally valid already, so force disconnect away from it.
+ if (!DisconnectTip(state)) {
+ return false;
+ }
+ }
+
+ // The resulting new best tip may not be in setBlockIndexCandidates anymore, so
+ // add them again.
+ BlockMap::iterator it = mapBlockIndex.begin();
+ while (it != mapBlockIndex.end()) {
+ if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) {
+ setBlockIndexCandidates.insert(pindex);
+ }
+ it++;
+ }
+
+ InvalidChainFound(pindex);
+ return true;
+}
+
+bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex) {
+ AssertLockHeld(cs_main);
+
+ int nHeight = pindex->nHeight;
+
+ // Remove the invalidity flag from this block and all its descendants.
+ BlockMap::iterator it = mapBlockIndex.begin();
+ while (it != mapBlockIndex.end()) {
+ if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) {
+ it->second->nStatus &= ~BLOCK_FAILED_MASK;
+ setDirtyBlockIndex.insert(it->second);
+ if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) {
+ setBlockIndexCandidates.insert(it->second);
+ }
+ if (it->second == pindexBestInvalid) {
+ // Reset invalid block marker if it was pointing to one of those.
+ pindexBestInvalid = NULL;
+ }
+ }
+ it++;
+ }
+
+ // Remove the invalidity flag from all ancestors too.
+ while (pindex != NULL) {
+ if (pindex->nStatus & BLOCK_FAILED_MASK) {
+ pindex->nStatus &= ~BLOCK_FAILED_MASK;
+ setDirtyBlockIndex.insert(pindex);
+ }
+ pindex = pindex->pprev;
+ }
+ return true;
+}
+
CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
{
// Check for duplicate
@@ -3113,75 +3180,6 @@ bool InitBlockIndex() {
-void PrintBlockTree()
-{
- AssertLockHeld(cs_main);
- // pre-compute tree structure
- map<CBlockIndex*, vector<CBlockIndex*> > mapNext;
- for (BlockMap::iterator mi = mapBlockIndex.begin(); mi != mapBlockIndex.end(); ++mi)
- {
- CBlockIndex* pindex = (*mi).second;
- mapNext[pindex->pprev].push_back(pindex);
- // test
- //while (rand() % 3 == 0)
- // mapNext[pindex->pprev].push_back(pindex);
- }
-
- vector<pair<int, CBlockIndex*> > vStack;
- vStack.push_back(make_pair(0, chainActive.Genesis()));
-
- int nPrevCol = 0;
- while (!vStack.empty())
- {
- int nCol = vStack.back().first;
- CBlockIndex* pindex = vStack.back().second;
- vStack.pop_back();
-
- // print split or gap
- if (nCol > nPrevCol)
- {
- for (int i = 0; i < nCol-1; i++)
- LogPrintf("| ");
- LogPrintf("|\\\n");
- }
- else if (nCol < nPrevCol)
- {
- for (int i = 0; i < nCol; i++)
- LogPrintf("| ");
- LogPrintf("|\n");
- }
- nPrevCol = nCol;
-
- // print columns
- for (int i = 0; i < nCol; i++)
- LogPrintf("| ");
-
- // print item
- CBlock block;
- ReadBlockFromDisk(block, pindex);
- LogPrintf("%d (blk%05u.dat:0x%x) %s tx %u\n",
- pindex->nHeight,
- pindex->GetBlockPos().nFile, pindex->GetBlockPos().nPos,
- DateTimeStrFormat("%Y-%m-%d %H:%M:%S", block.GetBlockTime()),
- block.vtx.size());
-
- // put the main time-chain first
- vector<CBlockIndex*>& vNext = mapNext[pindex];
- for (unsigned int i = 0; i < vNext.size(); i++)
- {
- if (chainActive.Next(vNext[i]))
- {
- swap(vNext[0], vNext[i]);
- break;
- }
- }
-
- // iterate children
- for (unsigned int i = 0; i < vNext.size(); i++)
- vStack.push_back(make_pair(nCol+i, vNext[i]));
- }
-}
-
bool LoadExternalBlockFile(FILE* fileIn, CDiskBlockPos *dbp)
{
// Map of disk positions for blocks with unknown parent (only used for reindex)
diff --git a/src/main.h b/src/main.h
index c0d6412528..caf8331ee1 100644
--- a/src/main.h
+++ b/src/main.h
@@ -177,8 +177,6 @@ bool InitBlockIndex();
bool LoadBlockIndex();
/** Unload database information */
void UnloadBlockIndex();
-/** Print the loaded block tree */
-void PrintBlockTree();
/** Process protocol messages received from a given node */
bool ProcessMessages(CNode* pfrom);
/** Send queued protocol messages to be sent to a give node */
@@ -609,6 +607,12 @@ public:
/** Find the last common block between the parameter chain and a locator. */
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator);
+/** Mark a block as invalid. */
+bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex);
+
+/** Remove invalidity status from a block and its descendants. */
+bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex);
+
/** The currently-connected chain of blocks. */
extern CChain chainActive;
diff --git a/src/netbase.cpp b/src/netbase.cpp
index ea05b8766f..aca5a107fe 100644
--- a/src/netbase.cpp
+++ b/src/netbase.cpp
@@ -4,7 +4,7 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifdef HAVE_CONFIG_H
-#include "bitcoin-config.h"
+#include "config/bitcoin-config.h"
#endif
#include "netbase.h"
diff --git a/src/qt/bitcoinunits.cpp b/src/qt/bitcoinunits.cpp
index c85f569fd3..75e1f9ae78 100644
--- a/src/qt/bitcoinunits.cpp
+++ b/src/qt/bitcoinunits.cpp
@@ -106,10 +106,8 @@ QString BitcoinUnits::format(int unit, const CAmount& nIn, bool fPlus, Separator
QString quotient_str = QString::number(quotient);
QString remainder_str = QString::number(remainder).rightJustified(num_decimals, '0');
- // Use SI-stule separators as these are locale indendent and can't be
- // confused with the decimal marker. Rule is to use a thin space every
- // three digits on *both* sides of the decimal point - but only if there
- // are five or more digits
+ // Use SI-style thin space separators as these are locale independent and can't be
+ // confused with the decimal marker.
QChar thin_sp(THIN_SP_CP);
int q_size = quotient_str.size();
if (separators == separatorAlways || (separators == separatorStandard && q_size > 4))
diff --git a/src/random.h b/src/random.h
index ec73d910c4..aa55ca2b6f 100644
--- a/src/random.h
+++ b/src/random.h
@@ -26,7 +26,7 @@ uint256 GetRandHash();
/**
* Seed insecure_rand using the random pool.
- * @param Deterministic Use a determinstic seed
+ * @param Deterministic Use a deterministic seed
*/
void seed_insecure_rand(bool fDeterministic = false);
diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp
index 5c4ee691dd..045cd90ef6 100644
--- a/src/rpcblockchain.cpp
+++ b/src/rpcblockchain.cpp
@@ -588,3 +588,79 @@ Value getmempoolinfo(const Array& params, bool fHelp)
return ret;
}
+Value invalidateblock(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "invalidateblock \"hash\"\n"
+ "\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"
+ "\nArguments:\n"
+ "1. hash (string, required) the hash of the block to mark as invalid\n"
+ "\nResult:\n"
+ "\nExamples:\n"
+ + HelpExampleCli("invalidateblock", "\"blockhash\"")
+ + HelpExampleRpc("invalidateblock", "\"blockhash\"")
+ );
+
+ std::string strHash = params[0].get_str();
+ uint256 hash(strHash);
+ CValidationState state;
+
+ {
+ LOCK(cs_main);
+ if (mapBlockIndex.count(hash) == 0)
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
+
+ CBlockIndex* pblockindex = mapBlockIndex[hash];
+ InvalidateBlock(state, pblockindex);
+ }
+
+ if (state.IsValid()) {
+ ActivateBestChain(state);
+ }
+
+ if (!state.IsValid()) {
+ throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
+ }
+
+ return Value::null;
+}
+
+Value reconsiderblock(const Array& params, bool fHelp)
+{
+ if (fHelp || params.size() != 1)
+ throw runtime_error(
+ "reconsiderblock \"hash\"\n"
+ "\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
+ "This can be used to undo the effects of invalidateblock.\n"
+ "\nArguments:\n"
+ "1. hash (string, required) the hash of the block to reconsider\n"
+ "\nResult:\n"
+ "\nExamples:\n"
+ + HelpExampleCli("reconsiderblock", "\"blockhash\"")
+ + HelpExampleRpc("reconsiderblock", "\"blockhash\"")
+ );
+
+ std::string strHash = params[0].get_str();
+ uint256 hash(strHash);
+ CValidationState state;
+
+ {
+ LOCK(cs_main);
+ if (mapBlockIndex.count(hash) == 0)
+ throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
+
+ CBlockIndex* pblockindex = mapBlockIndex[hash];
+ ReconsiderBlock(state, pblockindex);
+ }
+
+ if (state.IsValid()) {
+ ActivateBestChain(state);
+ }
+
+ if (!state.IsValid()) {
+ throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
+ }
+
+ return Value::null;
+}
diff --git a/src/rpcserver.cpp b/src/rpcserver.cpp
index b03016a508..8512212185 100644
--- a/src/rpcserver.cpp
+++ b/src/rpcserver.cpp
@@ -160,7 +160,7 @@ string CRPCTable::help(string strCommand) const
// We already filter duplicates, but these deprecated screw up the sort order
if (strMethod.find("label") != string::npos)
continue;
- if (strCommand != "" && strMethod != strCommand)
+ if ((strCommand != "" || pcmd->category == "hidden") && strMethod != strCommand)
continue;
#ifdef ENABLE_WALLET
if (pcmd->reqWallet && !pwalletMain)
@@ -246,7 +246,6 @@ static const CRPCCommand vRPCCommands[] =
{ "control", "getinfo", &getinfo, true, false, false }, /* uses wallet if enabled */
{ "control", "help", &help, true, true, false },
{ "control", "stop", &stop, true, true, false },
- { "control", "setmocktime", &setmocktime, true, false, false },
/* P2P networking */
{ "network", "getnetworkinfo", &getnetworkinfo, true, false, false },
@@ -300,6 +299,11 @@ static const CRPCCommand vRPCCommands[] =
{ "util", "estimatefee", &estimatefee, true, true, false },
{ "util", "estimatepriority", &estimatepriority, true, true, false },
+ /* Not shown in help */
+ { "hidden", "invalidateblock", &invalidateblock, true, true, false },
+ { "hidden", "reconsiderblock", &reconsiderblock, true, true, false },
+ { "hidden", "setmocktime", &setmocktime, true, false, false },
+
#ifdef ENABLE_WALLET
/* Wallet */
{ "wallet", "addmultisigaddress", &addmultisigaddress, true, false, true },
diff --git a/src/rpcserver.h b/src/rpcserver.h
index b0e437057b..2b2428445d 100644
--- a/src/rpcserver.h
+++ b/src/rpcserver.h
@@ -222,6 +222,8 @@ extern json_spirit::Value gettxoutsetinfo(const json_spirit::Array& params, bool
extern json_spirit::Value gettxout(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value verifychain(const json_spirit::Array& params, bool fHelp);
extern json_spirit::Value getchaintips(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value invalidateblock(const json_spirit::Array& params, bool fHelp);
+extern json_spirit::Value reconsiderblock(const json_spirit::Array& params, bool fHelp);
// in rest.cpp
extern bool HTTPReq_REST(AcceptedConnection *conn,