Add preciousblock RPC
Includes a bugfix by Luke-Jr.
This commit is contained in:
parent
c072b8fd95
commit
5127c4f21c
4 changed files with 80 additions and 3 deletions
|
@ -200,7 +200,7 @@ public:
|
|||
unsigned int nNonce;
|
||||
|
||||
//! (memory only) Sequential id assigned to distinguish order in which blocks are received.
|
||||
uint32_t nSequenceId;
|
||||
int32_t nSequenceId;
|
||||
|
||||
void SetNull()
|
||||
{
|
||||
|
|
38
src/main.cpp
38
src/main.cpp
|
@ -167,7 +167,11 @@ namespace {
|
|||
*/
|
||||
CCriticalSection cs_nBlockSequenceId;
|
||||
/** Blocks loaded from disk are assigned id 0, so start the counter at 1. */
|
||||
uint32_t nBlockSequenceId = 1;
|
||||
int32_t nBlockSequenceId = 1;
|
||||
/** Decreasing counter (used by subsequent preciousblock calls). */
|
||||
int32_t nBlockReverseSequenceId = -1;
|
||||
/** chainwork for the last block that preciousblock has been applied to. */
|
||||
arith_uint256 nLastPreciousChainwork = 0;
|
||||
|
||||
/**
|
||||
* Sources of received blocks, saved to be able to send them reject
|
||||
|
@ -3107,6 +3111,36 @@ bool ActivateBestChain(CValidationState &state, const CChainParams& chainparams,
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex)
|
||||
{
|
||||
{
|
||||
LOCK(cs_main);
|
||||
if (pindex->nChainWork < chainActive.Tip()->nChainWork) {
|
||||
// Nothing to do, this block is not at the tip.
|
||||
return true;
|
||||
}
|
||||
if (chainActive.Tip()->nChainWork > nLastPreciousChainwork) {
|
||||
// The chain has been extended since the last call, reset the counter.
|
||||
nBlockReverseSequenceId = -1;
|
||||
}
|
||||
nLastPreciousChainwork = chainActive.Tip()->nChainWork;
|
||||
setBlockIndexCandidates.erase(pindex);
|
||||
pindex->nSequenceId = nBlockReverseSequenceId;
|
||||
if (nBlockReverseSequenceId > std::numeric_limits<int32_t>::min()) {
|
||||
// We can't keep reducing the counter if somebody really wants to
|
||||
// call preciousblock 2**31-1 times on the same set of tips...
|
||||
nBlockReverseSequenceId--;
|
||||
}
|
||||
if (pindex->IsValid(BLOCK_VALID_TRANSACTIONS) && pindex->nChainTx) {
|
||||
setBlockIndexCandidates.insert(pindex);
|
||||
PruneBlockIndexCandidates();
|
||||
}
|
||||
}
|
||||
|
||||
return ActivateBestChain(state, params);
|
||||
}
|
||||
|
||||
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex)
|
||||
{
|
||||
AssertLockHeld(cs_main);
|
||||
|
@ -4501,7 +4535,7 @@ void static CheckBlockIndex(const Consensus::Params& consensusParams)
|
|||
assert(pindex->GetBlockHash() == consensusParams.hashGenesisBlock); // Genesis block's hash must match.
|
||||
assert(pindex == chainActive.Genesis()); // The current active chain's genesis block must be this block.
|
||||
}
|
||||
if (pindex->nChainTx == 0) assert(pindex->nSequenceId == 0); // nSequenceId can't be set for blocks that aren't linked
|
||||
if (pindex->nChainTx == 0) assert(pindex->nSequenceId <= 0); // nSequenceId can't be set positive for blocks that aren't linked (negative is used for preciousblock)
|
||||
// VALID_TRANSACTIONS is equivalent to nTx > 0 for all nodes (whether or not pruning has occurred).
|
||||
// HAVE_DATA is only equivalent to nTx > 0 (or VALID_TRANSACTIONS) if no pruning has occurred.
|
||||
if (!fHavePruned) {
|
||||
|
|
|
@ -499,6 +499,9 @@ 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 precious and reorganize. */
|
||||
bool PreciousBlock(CValidationState& state, const CChainParams& params, CBlockIndex *pindex);
|
||||
|
||||
/** Mark a block as invalid. */
|
||||
bool InvalidateBlock(CValidationState& state, const CChainParams& chainparams, CBlockIndex *pindex);
|
||||
|
||||
|
|
|
@ -1105,6 +1105,44 @@ UniValue getmempoolinfo(const UniValue& params, bool fHelp)
|
|||
return mempoolInfoToJSON();
|
||||
}
|
||||
|
||||
UniValue preciousblock(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
throw runtime_error(
|
||||
"preciousblock \"hash\"\n"
|
||||
"\nTreats a block as if it were received before others with the same work.\n"
|
||||
"\nA later preciousblock call can override the effect of an earlier one.\n"
|
||||
"\nThe effects of preciousblock are not retained across restarts.\n"
|
||||
"\nArguments:\n"
|
||||
"1. hash (string, required) the hash of the block to mark as precious\n"
|
||||
"\nResult:\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("preciousblock", "\"blockhash\"")
|
||||
+ HelpExampleRpc("preciousblock", "\"blockhash\"")
|
||||
);
|
||||
|
||||
std::string strHash = params[0].get_str();
|
||||
uint256 hash(uint256S(strHash));
|
||||
CBlockIndex* pblockindex;
|
||||
|
||||
{
|
||||
LOCK(cs_main);
|
||||
if (mapBlockIndex.count(hash) == 0)
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
|
||||
|
||||
pblockindex = mapBlockIndex[hash];
|
||||
}
|
||||
|
||||
CValidationState state;
|
||||
PreciousBlock(state, Params(), pblockindex);
|
||||
|
||||
if (!state.IsValid()) {
|
||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason());
|
||||
}
|
||||
|
||||
return NullUniValue;
|
||||
}
|
||||
|
||||
UniValue invalidateblock(const UniValue& params, bool fHelp)
|
||||
{
|
||||
if (fHelp || params.size() != 1)
|
||||
|
@ -1200,6 +1238,8 @@ static const CRPCCommand commands[] =
|
|||
{ "blockchain", "gettxoutsetinfo", &gettxoutsetinfo, true },
|
||||
{ "blockchain", "verifychain", &verifychain, true },
|
||||
|
||||
{ "blockchain", "preciousblock", &preciousblock, true },
|
||||
|
||||
/* Not shown in help */
|
||||
{ "hidden", "invalidateblock", &invalidateblock, true },
|
||||
{ "hidden", "reconsiderblock", &reconsiderblock, true },
|
||||
|
|
Loading…
Reference in a new issue