Skip to content

Commit d7c8a83

Browse files
committed
Merge pull request #5316
f86a24b Move `setmocktime` to hidden category (Wladimir J. van der Laan) bd9aebf Introduce a hidden category (Pieter Wuille) 0dd06b2 Delay writing block indexes in invalidate/reconsider (Pieter Wuille) 9b0a8d3 Add 'invalidateblock' and 'reconsiderblock' RPC commands. (Pieter Wuille)
2 parents 631e698 + f86a24b commit d7c8a83

File tree

5 files changed

+157
-2
lines changed

5 files changed

+157
-2
lines changed

src/main.cpp

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2135,6 +2135,73 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) {
21352135
return true;
21362136
}
21372137

2138+
bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex) {
2139+
AssertLockHeld(cs_main);
2140+
2141+
// Mark the block itself as invalid.
2142+
pindex->nStatus |= BLOCK_FAILED_VALID;
2143+
setDirtyBlockIndex.insert(pindex);
2144+
setBlockIndexCandidates.erase(pindex);
2145+
2146+
while (chainActive.Contains(pindex)) {
2147+
CBlockIndex *pindexWalk = chainActive.Tip();
2148+
pindexWalk->nStatus |= BLOCK_FAILED_CHILD;
2149+
setDirtyBlockIndex.insert(pindexWalk);
2150+
setBlockIndexCandidates.erase(pindexWalk);
2151+
// ActivateBestChain considers blocks already in chainActive
2152+
// unconditionally valid already, so force disconnect away from it.
2153+
if (!DisconnectTip(state)) {
2154+
return false;
2155+
}
2156+
}
2157+
2158+
// The resulting new best tip may not be in setBlockIndexCandidates anymore, so
2159+
// add them again.
2160+
BlockMap::iterator it = mapBlockIndex.begin();
2161+
while (it != mapBlockIndex.end()) {
2162+
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) {
2163+
setBlockIndexCandidates.insert(pindex);
2164+
}
2165+
it++;
2166+
}
2167+
2168+
InvalidChainFound(pindex);
2169+
return true;
2170+
}
2171+
2172+
bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex) {
2173+
AssertLockHeld(cs_main);
2174+
2175+
int nHeight = pindex->nHeight;
2176+
2177+
// Remove the invalidity flag from this block and all its descendants.
2178+
BlockMap::iterator it = mapBlockIndex.begin();
2179+
while (it != mapBlockIndex.end()) {
2180+
if (!it->second->IsValid() && it->second->GetAncestor(nHeight) == pindex) {
2181+
it->second->nStatus &= ~BLOCK_FAILED_MASK;
2182+
setDirtyBlockIndex.insert(it->second);
2183+
if (it->second->IsValid(BLOCK_VALID_TRANSACTIONS) && it->second->nChainTx && setBlockIndexCandidates.value_comp()(chainActive.Tip(), it->second)) {
2184+
setBlockIndexCandidates.insert(it->second);
2185+
}
2186+
if (it->second == pindexBestInvalid) {
2187+
// Reset invalid block marker if it was pointing to one of those.
2188+
pindexBestInvalid = NULL;
2189+
}
2190+
}
2191+
it++;
2192+
}
2193+
2194+
// Remove the invalidity flag from all ancestors too.
2195+
while (pindex != NULL) {
2196+
if (pindex->nStatus & BLOCK_FAILED_MASK) {
2197+
pindex->nStatus &= ~BLOCK_FAILED_MASK;
2198+
setDirtyBlockIndex.insert(pindex);
2199+
}
2200+
pindex = pindex->pprev;
2201+
}
2202+
return true;
2203+
}
2204+
21382205
CBlockIndex* AddToBlockIndex(const CBlockHeader& block)
21392206
{
21402207
// Check for duplicate

src/main.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -607,6 +607,12 @@ class CVerifyDB {
607607
/** Find the last common block between the parameter chain and a locator. */
608608
CBlockIndex* FindForkInGlobalIndex(const CChain& chain, const CBlockLocator& locator);
609609

610+
/** Mark a block as invalid. */
611+
bool InvalidateBlock(CValidationState& state, CBlockIndex *pindex);
612+
613+
/** Remove invalidity status from a block and its descendants. */
614+
bool ReconsiderBlock(CValidationState& state, CBlockIndex *pindex);
615+
610616
/** The currently-connected chain of blocks. */
611617
extern CChain chainActive;
612618

src/rpcblockchain.cpp

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,3 +561,79 @@ Value getmempoolinfo(const Array& params, bool fHelp)
561561
return ret;
562562
}
563563

564+
Value invalidateblock(const Array& params, bool fHelp)
565+
{
566+
if (fHelp || params.size() != 1)
567+
throw runtime_error(
568+
"invalidateblock \"hash\"\n"
569+
"\nPermanently marks a block as invalid, as if it violated a consensus rule.\n"
570+
"\nArguments:\n"
571+
"1. hash (string, required) the hash of the block to mark as invalid\n"
572+
"\nResult:\n"
573+
"\nExamples:\n"
574+
+ HelpExampleCli("invalidateblock", "\"blockhash\"")
575+
+ HelpExampleRpc("invalidateblock", "\"blockhash\"")
576+
);
577+
578+
std::string strHash = params[0].get_str();
579+
uint256 hash(strHash);
580+
CValidationState state;
581+
582+
{
583+
LOCK(cs_main);
584+
if (mapBlockIndex.count(hash) == 0)
585+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
586+
587+
CBlockIndex* pblockindex = mapBlockIndex[hash];
588+
InvalidateBlock(state, pblockindex);
589+
}
590+
591+
if (state.IsValid()) {
592+
ActivateBestChain(state);
593+
}
594+
595+
if (!state.IsValid()) {
596+
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
597+
}
598+
599+
return Value::null;
600+
}
601+
602+
Value reconsiderblock(const Array& params, bool fHelp)
603+
{
604+
if (fHelp || params.size() != 1)
605+
throw runtime_error(
606+
"reconsiderblock \"hash\"\n"
607+
"\nRemoves invalidity status of a block and its descendants, reconsider them for activation.\n"
608+
"This can be used to undo the effects of invalidateblock.\n"
609+
"\nArguments:\n"
610+
"1. hash (string, required) the hash of the block to reconsider\n"
611+
"\nResult:\n"
612+
"\nExamples:\n"
613+
+ HelpExampleCli("reconsiderblock", "\"blockhash\"")
614+
+ HelpExampleRpc("reconsiderblock", "\"blockhash\"")
615+
);
616+
617+
std::string strHash = params[0].get_str();
618+
uint256 hash(strHash);
619+
CValidationState state;
620+
621+
{
622+
LOCK(cs_main);
623+
if (mapBlockIndex.count(hash) == 0)
624+
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
625+
626+
CBlockIndex* pblockindex = mapBlockIndex[hash];
627+
ReconsiderBlock(state, pblockindex);
628+
}
629+
630+
if (state.IsValid()) {
631+
ActivateBestChain(state);
632+
}
633+
634+
if (!state.IsValid()) {
635+
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
636+
}
637+
638+
return Value::null;
639+
}

src/rpcserver.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ string CRPCTable::help(string strCommand) const
160160
// We already filter duplicates, but these deprecated screw up the sort order
161161
if (strMethod.find("label") != string::npos)
162162
continue;
163-
if (strCommand != "" && strMethod != strCommand)
163+
if ((strCommand != "" || pcmd->category == "hidden") && strMethod != strCommand)
164164
continue;
165165
#ifdef ENABLE_WALLET
166166
if (pcmd->reqWallet && !pwalletMain)
@@ -246,7 +246,6 @@ static const CRPCCommand vRPCCommands[] =
246246
{ "control", "getinfo", &getinfo, true, false, false }, /* uses wallet if enabled */
247247
{ "control", "help", &help, true, true, false },
248248
{ "control", "stop", &stop, true, true, false },
249-
{ "control", "setmocktime", &setmocktime, true, false, false },
250249

251250
/* P2P networking */
252251
{ "network", "getnetworkinfo", &getnetworkinfo, true, false, false },
@@ -300,6 +299,11 @@ static const CRPCCommand vRPCCommands[] =
300299
{ "util", "estimatefee", &estimatefee, true, true, false },
301300
{ "util", "estimatepriority", &estimatepriority, true, true, false },
302301

302+
/* Not shown in help */
303+
{ "hidden", "invalidateblock", &invalidateblock, true, true, false },
304+
{ "hidden", "reconsiderblock", &reconsiderblock, true, true, false },
305+
{ "hidden", "setmocktime", &setmocktime, true, false, false },
306+
303307
#ifdef ENABLE_WALLET
304308
/* Wallet */
305309
{ "wallet", "addmultisigaddress", &addmultisigaddress, true, false, true },

src/rpcserver.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ extern json_spirit::Value gettxoutsetinfo(const json_spirit::Array& params, bool
222222
extern json_spirit::Value gettxout(const json_spirit::Array& params, bool fHelp);
223223
extern json_spirit::Value verifychain(const json_spirit::Array& params, bool fHelp);
224224
extern json_spirit::Value getchaintips(const json_spirit::Array& params, bool fHelp);
225+
extern json_spirit::Value invalidateblock(const json_spirit::Array& params, bool fHelp);
226+
extern json_spirit::Value reconsiderblock(const json_spirit::Array& params, bool fHelp);
225227

226228
// in rest.cpp
227229
extern bool HTTPReq_REST(AcceptedConnection *conn,

0 commit comments

Comments
 (0)