Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/blockchain.cpp
Show First 20 Lines • Show All 160 Lines • ▼ Show 20 Lines | if (request.fHelp || request.params.size() != 0) { | ||||
"\nResult:\n" | "\nResult:\n" | ||||
"n (numeric) The current block count\n" | "n (numeric) The current block count\n" | ||||
"\nExamples:\n" + | "\nExamples:\n" + | ||||
HelpExampleCli("getblockcount", "") + | HelpExampleCli("getblockcount", "") + | ||||
HelpExampleRpc("getblockcount", "")); | HelpExampleRpc("getblockcount", "")); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return chainActive.Height(); | return ::ChainActive().Height(); | ||||
} | } | ||||
static UniValue getbestblockhash(const Config &config, | static UniValue getbestblockhash(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 0) { | if (request.fHelp || request.params.size() != 0) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"getbestblockhash\n" | "getbestblockhash\n" | ||||
"\nReturns the hash of the best (tip) block in the " | "\nReturns the hash of the best (tip) block in the " | ||||
"longest blockchain.\n" | "longest blockchain.\n" | ||||
"\nResult:\n" | "\nResult:\n" | ||||
"\"hex\" (string) the block hash hex encoded\n" | "\"hex\" (string) the block hash hex encoded\n" | ||||
"\nExamples:\n" + | "\nExamples:\n" + | ||||
HelpExampleCli("getbestblockhash", "") + | HelpExampleCli("getbestblockhash", "") + | ||||
HelpExampleRpc("getbestblockhash", "")); | HelpExampleRpc("getbestblockhash", "")); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return chainActive.Tip()->GetBlockHash().GetHex(); | return ::ChainActive().Tip()->GetBlockHash().GetHex(); | ||||
} | } | ||||
UniValue getfinalizedblockhash(const Config &config, | UniValue getfinalizedblockhash(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() != 0) { | if (request.fHelp || request.params.size() != 0) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
"getfinalizedblockhash\n" | "getfinalizedblockhash\n" | ||||
"\nReturns the hash of the currently finalized block\n" | "\nReturns the hash of the currently finalized block\n" | ||||
▲ Show 20 Lines • Show All 206 Lines • ▼ Show 20 Lines | if (request.fHelp || request.params.size() != 0) { | ||||
"difficulty as a multiple of the minimum " | "difficulty as a multiple of the minimum " | ||||
"difficulty.\n" | "difficulty.\n" | ||||
"\nExamples:\n" + | "\nExamples:\n" + | ||||
HelpExampleCli("getdifficulty", "") + | HelpExampleCli("getdifficulty", "") + | ||||
HelpExampleRpc("getdifficulty", "")); | HelpExampleRpc("getdifficulty", "")); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return GetDifficulty(chainActive.Tip()); | return GetDifficulty(::ChainActive().Tip()); | ||||
} | } | ||||
static std::string EntryDescriptionString() { | static std::string EntryDescriptionString() { | ||||
return " \"size\" : n, (numeric) transaction size.\n" | return " \"size\" : n, (numeric) transaction size.\n" | ||||
" \"fee\" : n, (numeric) transaction fee in " + | " \"fee\" : n, (numeric) transaction fee in " + | ||||
CURRENCY_UNIT + "(DEPRECATED)" + | CURRENCY_UNIT + "(DEPRECATED)" + | ||||
"\n" | "\n" | ||||
" \"modifiedfee\" : n, (numeric) transaction fee with fee " | " \"modifiedfee\" : n, (numeric) transaction fee with fee " | ||||
▲ Show 20 Lines • Show All 335 Lines • ▼ Show 20 Lines | if (request.fHelp || request.params.size() != 1) { | ||||
"\nExamples:\n" + | "\nExamples:\n" + | ||||
HelpExampleCli("getblockhash", "1000") + | HelpExampleCli("getblockhash", "1000") + | ||||
HelpExampleRpc("getblockhash", "1000")); | HelpExampleRpc("getblockhash", "1000")); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
int nHeight = request.params[0].get_int(); | int nHeight = request.params[0].get_int(); | ||||
if (nHeight < 0 || nHeight > chainActive.Height()) { | if (nHeight < 0 || nHeight > ::ChainActive().Height()) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); | throw JSONRPCError(RPC_INVALID_PARAMETER, "Block height out of range"); | ||||
} | } | ||||
CBlockIndex *pblockindex = chainActive[nHeight]; | CBlockIndex *pblockindex = ::ChainActive()[nHeight]; | ||||
return pblockindex->GetBlockHash().GetHex(); | return pblockindex->GetBlockHash().GetHex(); | ||||
} | } | ||||
static UniValue getblockheader(const Config &config, | static UniValue getblockheader(const Config &config, | ||||
const JSONRPCRequest &request) { | const JSONRPCRequest &request) { | ||||
if (request.fHelp || request.params.size() < 1 || | if (request.fHelp || request.params.size() < 1 || | ||||
request.params.size() > 2) { | request.params.size() > 2) { | ||||
throw std::runtime_error( | throw std::runtime_error( | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | if (!request.params[1].isNull()) { | ||||
fVerbose = request.params[1].get_bool(); | fVerbose = request.params[1].get_bool(); | ||||
} | } | ||||
const CBlockIndex *pblockindex; | const CBlockIndex *pblockindex; | ||||
const CBlockIndex *tip; | const CBlockIndex *tip; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pblockindex = LookupBlockIndex(hash); | pblockindex = LookupBlockIndex(hash); | ||||
tip = chainActive.Tip(); | tip = ::ChainActive().Tip(); | ||||
} | } | ||||
if (!pblockindex) { | if (!pblockindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | ||||
} | } | ||||
if (!fVerbose) { | if (!fVerbose) { | ||||
CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); | CDataStream ssBlock(SER_NETWORK, PROTOCOL_VERSION); | ||||
▲ Show 20 Lines • Show All 115 Lines • ▼ Show 20 Lines | static UniValue getblock(const Config &config, const JSONRPCRequest &request) { | ||||
if (verbosity <= 0) { | if (verbosity <= 0) { | ||||
CDataStream ssBlock(SER_NETWORK, | CDataStream ssBlock(SER_NETWORK, | ||||
PROTOCOL_VERSION | RPCSerializationFlags()); | PROTOCOL_VERSION | RPCSerializationFlags()); | ||||
ssBlock << block; | ssBlock << block; | ||||
std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); | std::string strHex = HexStr(ssBlock.begin(), ssBlock.end()); | ||||
return strHex; | return strHex; | ||||
} | } | ||||
return blockToJSON(block, chainActive.Tip(), pblockindex, verbosity >= 2); | return blockToJSON(block, ::ChainActive().Tip(), pblockindex, | ||||
verbosity >= 2); | |||||
} | } | ||||
struct CCoinsStats { | struct CCoinsStats { | ||||
int nHeight; | int nHeight; | ||||
BlockHash hashBlock; | BlockHash hashBlock; | ||||
uint64_t nTransactions; | uint64_t nTransactions; | ||||
uint64_t nTransactionOutputs; | uint64_t nTransactionOutputs; | ||||
uint64_t nBogoSize; | uint64_t nBogoSize; | ||||
▲ Show 20 Lines • Show All 97 Lines • ▼ Show 20 Lines | static UniValue pruneblockchain(const Config &config, | ||||
} | } | ||||
// Height value more than a billion is too high to be a block height, and | // Height value more than a billion is too high to be a block height, and | ||||
// too low to be a block time (corresponds to timestamp from Sep 2001). | // too low to be a block time (corresponds to timestamp from Sep 2001). | ||||
if (heightParam > 1000000000) { | if (heightParam > 1000000000) { | ||||
// Add a 2 hour buffer to include blocks which might have had old | // Add a 2 hour buffer to include blocks which might have had old | ||||
// timestamps | // timestamps | ||||
CBlockIndex *pindex = | CBlockIndex *pindex = | ||||
chainActive.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW); | ::ChainActive().FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW); | ||||
if (!pindex) { | if (!pindex) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_PARAMETER, | RPC_INVALID_PARAMETER, | ||||
"Could not find block with at least the specified timestamp."); | "Could not find block with at least the specified timestamp."); | ||||
} | } | ||||
heightParam = pindex->nHeight; | heightParam = pindex->nHeight; | ||||
} | } | ||||
unsigned int height = (unsigned int)heightParam; | unsigned int height = (unsigned int)heightParam; | ||||
unsigned int chainHeight = (unsigned int)chainActive.Height(); | unsigned int chainHeight = (unsigned int)::ChainActive().Height(); | ||||
if (chainHeight < config.GetChainParams().PruneAfterHeight()) { | if (chainHeight < config.GetChainParams().PruneAfterHeight()) { | ||||
throw JSONRPCError(RPC_MISC_ERROR, | throw JSONRPCError(RPC_MISC_ERROR, | ||||
"Blockchain is too short for pruning."); | "Blockchain is too short for pruning."); | ||||
} else if (height > chainHeight) { | } else if (height > chainHeight) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_PARAMETER, | RPC_INVALID_PARAMETER, | ||||
"Blockchain is shorter than the attempted prune height."); | "Blockchain is shorter than the attempted prune height."); | ||||
} else if (height > chainHeight - MIN_BLOCKS_TO_KEEP) { | } else if (height > chainHeight - MIN_BLOCKS_TO_KEEP) { | ||||
▲ Show 20 Lines • Show All 279 Lines • ▼ Show 20 Lines | if (request.fHelp || request.params.size() != 0) { | ||||
HelpExampleCli("getblockchaininfo", "") + | HelpExampleCli("getblockchaininfo", "") + | ||||
HelpExampleRpc("getblockchaininfo", "")); | HelpExampleRpc("getblockchaininfo", "")); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const CChainParams &chainparams = config.GetChainParams(); | const CChainParams &chainparams = config.GetChainParams(); | ||||
const CBlockIndex *tip = chainActive.Tip(); | const CBlockIndex *tip = ::ChainActive().Tip(); | ||||
UniValue obj(UniValue::VOBJ); | UniValue obj(UniValue::VOBJ); | ||||
obj.pushKV("chain", chainparams.NetworkIDString()); | obj.pushKV("chain", chainparams.NetworkIDString()); | ||||
obj.pushKV("blocks", int(chainActive.Height())); | obj.pushKV("blocks", int(::ChainActive().Height())); | ||||
obj.pushKV("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1); | obj.pushKV("headers", pindexBestHeader ? pindexBestHeader->nHeight : -1); | ||||
obj.pushKV("bestblockhash", tip->GetBlockHash().GetHex()); | obj.pushKV("bestblockhash", tip->GetBlockHash().GetHex()); | ||||
obj.pushKV("difficulty", double(GetDifficulty(tip))); | obj.pushKV("difficulty", double(GetDifficulty(tip))); | ||||
obj.pushKV("mediantime", int64_t(tip->GetMedianTimePast())); | obj.pushKV("mediantime", int64_t(tip->GetMedianTimePast())); | ||||
obj.pushKV("verificationprogress", | obj.pushKV("verificationprogress", | ||||
GuessVerificationProgress(Params().TxData(), tip)); | GuessVerificationProgress(Params().TxData(), tip)); | ||||
obj.pushKV("initialblockdownload", IsInitialBlockDownload()); | obj.pushKV("initialblockdownload", IsInitialBlockDownload()); | ||||
obj.pushKV("chainwork", tip->nChainWork.GetHex()); | obj.pushKV("chainwork", tip->nChainWork.GetHex()); | ||||
▲ Show 20 Lines • Show All 82 Lines • ▼ Show 20 Lines | if (request.fHelp || request.params.size() != 0) { | ||||
"\nExamples:\n" + | "\nExamples:\n" + | ||||
HelpExampleCli("getchaintips", "") + | HelpExampleCli("getchaintips", "") + | ||||
HelpExampleRpc("getchaintips", "")); | HelpExampleRpc("getchaintips", "")); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
/** | /** | ||||
* Idea: the set of chain tips is chainActive.tip, plus orphan blocks which | * Idea: the set of chain tips is ::ChainActive().tip, plus orphan blocks | ||||
* do not have another orphan building off of them. | * which do not have another orphan building off of them. Algorithm: | ||||
* Algorithm: | |||||
* - Make one pass through mapBlockIndex, picking out the orphan blocks, | * - Make one pass through mapBlockIndex, picking out the orphan blocks, | ||||
* and also storing a set of the orphan block's pprev pointers. | * and also storing a set of the orphan block's pprev pointers. | ||||
* - Iterate through the orphan blocks. If the block isn't pointed to by | * - Iterate through the orphan blocks. If the block isn't pointed to by | ||||
* another orphan, it is a chain tip. | * another orphan, it is a chain tip. | ||||
* - add chainActive.Tip() | * - add ::ChainActive().Tip() | ||||
*/ | */ | ||||
std::set<const CBlockIndex *, CompareBlocksByHeight> setTips; | std::set<const CBlockIndex *, CompareBlocksByHeight> setTips; | ||||
std::set<const CBlockIndex *> setOrphans; | std::set<const CBlockIndex *> setOrphans; | ||||
std::set<const CBlockIndex *> setPrevs; | std::set<const CBlockIndex *> setPrevs; | ||||
for (const std::pair<const BlockHash, CBlockIndex *> &item : | for (const std::pair<const BlockHash, CBlockIndex *> &item : | ||||
mapBlockIndex) { | mapBlockIndex) { | ||||
if (!chainActive.Contains(item.second)) { | if (!::ChainActive().Contains(item.second)) { | ||||
setOrphans.insert(item.second); | setOrphans.insert(item.second); | ||||
setPrevs.insert(item.second->pprev); | setPrevs.insert(item.second->pprev); | ||||
} | } | ||||
} | } | ||||
for (std::set<const CBlockIndex *>::iterator it = setOrphans.begin(); | for (std::set<const CBlockIndex *>::iterator it = setOrphans.begin(); | ||||
it != setOrphans.end(); ++it) { | it != setOrphans.end(); ++it) { | ||||
if (setPrevs.erase(*it) == 0) { | if (setPrevs.erase(*it) == 0) { | ||||
setTips.insert(*it); | setTips.insert(*it); | ||||
} | } | ||||
} | } | ||||
// Always report the currently active tip. | // Always report the currently active tip. | ||||
setTips.insert(chainActive.Tip()); | setTips.insert(::ChainActive().Tip()); | ||||
/* Construct the output array. */ | /* Construct the output array. */ | ||||
UniValue res(UniValue::VARR); | UniValue res(UniValue::VARR); | ||||
for (const CBlockIndex *block : setTips) { | for (const CBlockIndex *block : setTips) { | ||||
UniValue obj(UniValue::VOBJ); | UniValue obj(UniValue::VOBJ); | ||||
obj.pushKV("height", block->nHeight); | obj.pushKV("height", block->nHeight); | ||||
obj.pushKV("hash", block->phashBlock->GetHex()); | obj.pushKV("hash", block->phashBlock->GetHex()); | ||||
const int branchLen = | const int branchLen = | ||||
block->nHeight - chainActive.FindFork(block)->nHeight; | block->nHeight - ::ChainActive().FindFork(block)->nHeight; | ||||
obj.pushKV("branchlen", branchLen); | obj.pushKV("branchlen", branchLen); | ||||
std::string status; | std::string status; | ||||
if (chainActive.Contains(block)) { | if (::ChainActive().Contains(block)) { | ||||
// This block is part of the currently active chain. | // This block is part of the currently active chain. | ||||
status = "active"; | status = "active"; | ||||
} else if (block->nStatus.isInvalid()) { | } else if (block->nStatus.isInvalid()) { | ||||
// This block or one of its ancestors is invalid. | // This block or one of its ancestors is invalid. | ||||
status = "invalid"; | status = "invalid"; | ||||
} else if (block->nStatus.isOnParkedChain()) { | } else if (block->nStatus.isOnParkedChain()) { | ||||
// This block or one of its ancestors is parked. | // This block or one of its ancestors is parked. | ||||
status = "parked"; | status = "parked"; | ||||
▲ Show 20 Lines • Show All 348 Lines • ▼ Show 20 Lines | static UniValue getchaintxstats(const Config &config, | ||||
const CBlockIndex *pindex; | const CBlockIndex *pindex; | ||||
// By default: 1 month | // By default: 1 month | ||||
int blockcount = 30 * 24 * 60 * 60 / | int blockcount = 30 * 24 * 60 * 60 / | ||||
config.GetChainParams().GetConsensus().nPowTargetSpacing; | config.GetChainParams().GetConsensus().nPowTargetSpacing; | ||||
if (request.params[1].isNull()) { | if (request.params[1].isNull()) { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pindex = chainActive.Tip(); | pindex = ::ChainActive().Tip(); | ||||
} else { | } else { | ||||
BlockHash hash(ParseHashV(request.params[1], "blockhash")); | BlockHash hash(ParseHashV(request.params[1], "blockhash")); | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pindex = LookupBlockIndex(hash); | pindex = LookupBlockIndex(hash); | ||||
if (!pindex) { | if (!pindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | ||||
} | } | ||||
if (!chainActive.Contains(pindex)) { | if (!::ChainActive().Contains(pindex)) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"Block is not in main chain"); | "Block is not in main chain"); | ||||
} | } | ||||
} | } | ||||
assert(pindex != nullptr); | assert(pindex != nullptr); | ||||
if (request.params[0].isNull()) { | if (request.params[0].isNull()) { | ||||
▲ Show 20 Lines • Show All 137 Lines • ▼ Show 20 Lines | if (request.fHelp || request.params.size() < 1 || | ||||
"1000 '[\"minfeerate\",\"avgfeerate\"]'")); | "1000 '[\"minfeerate\",\"avgfeerate\"]'")); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CBlockIndex *pindex; | CBlockIndex *pindex; | ||||
if (request.params[0].isNum()) { | if (request.params[0].isNum()) { | ||||
const int height = request.params[0].get_int(); | const int height = request.params[0].get_int(); | ||||
const int current_tip = chainActive.Height(); | const int current_tip = ::ChainActive().Height(); | ||||
if (height < 0) { | if (height < 0) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_PARAMETER, | RPC_INVALID_PARAMETER, | ||||
strprintf("Target block height %d is negative", height)); | strprintf("Target block height %d is negative", height)); | ||||
} | } | ||||
if (height > current_tip) { | if (height > current_tip) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_PARAMETER, | RPC_INVALID_PARAMETER, | ||||
strprintf("Target block height %d after current tip %d", height, | strprintf("Target block height %d after current tip %d", height, | ||||
current_tip)); | current_tip)); | ||||
} | } | ||||
pindex = chainActive[height]; | pindex = ::ChainActive()[height]; | ||||
} else { | } else { | ||||
const BlockHash hash(ParseHashV(request.params[0], "hash_or_height")); | const BlockHash hash(ParseHashV(request.params[0], "hash_or_height")); | ||||
pindex = LookupBlockIndex(hash); | pindex = LookupBlockIndex(hash); | ||||
if (!pindex) { | if (!pindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found"); | ||||
} | } | ||||
if (!chainActive.Contains(pindex)) { | if (!::ChainActive().Contains(pindex)) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
strprintf("Block is not in chain %s", | strprintf("Block is not in chain %s", | ||||
Params().NetworkIDString())); | Params().NetworkIDString())); | ||||
} | } | ||||
} | } | ||||
assert(pindex != nullptr); | assert(pindex != nullptr); | ||||
▲ Show 20 Lines • Show All 518 Lines • Show Last 20 Lines |