diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/init.cpp | 30 | ||||
-rw-r--r-- | src/main.cpp | 136 | ||||
-rw-r--r-- | src/main.h | 8 | ||||
-rw-r--r-- | src/netbase.cpp | 2 | ||||
-rw-r--r-- | src/qt/bitcoinunits.cpp | 6 | ||||
-rw-r--r-- | src/random.h | 2 | ||||
-rw-r--r-- | src/rpcblockchain.cpp | 76 | ||||
-rw-r--r-- | src/rpcserver.cpp | 8 | ||||
-rw-r--r-- | src/rpcserver.h | 2 |
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, |