Browse Source

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)
0.10
Wladimir J. van der Laan 10 years ago
parent
commit
d7c8a830c4
No known key found for this signature in database
GPG Key ID: 74810B012346C9A6
  1. 67
      src/main.cpp
  2. 6
      src/main.h
  3. 76
      src/rpcblockchain.cpp
  4. 8
      src/rpcserver.cpp
  5. 2
      src/rpcserver.h

67
src/main.cpp

@ -2135,6 +2135,73 @@ bool ActivateBestChain(CValidationState &state, CBlock *pblock) { @@ -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

6
src/main.h

@ -607,6 +607,12 @@ public: @@ -607,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;

76
src/rpcblockchain.cpp

@ -561,3 +561,79 @@ Value getmempoolinfo(const Array& params, bool fHelp) @@ -561,3 +561,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;
}

8
src/rpcserver.cpp

@ -160,7 +160,7 @@ string CRPCTable::help(string strCommand) const @@ -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[] = @@ -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[] = @@ -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 },

2
src/rpcserver.h

@ -222,6 +222,8 @@ extern json_spirit::Value gettxoutsetinfo(const json_spirit::Array& params, bool @@ -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,

Loading…
Cancel
Save