Changeset View
Changeset View
Standalone View
Standalone View
src/rpc/blockchain.cpp
Show First 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
"The genesis block has height 0.\n", | "The genesis block has height 0.\n", | ||||
{}, | {}, | ||||
RPCResult{RPCResult::Type::NUM, "", "The current block count"}, | RPCResult{RPCResult::Type::NUM, "", "The current block count"}, | ||||
RPCExamples{HelpExampleCli("getblockcount", "") + | RPCExamples{HelpExampleCli("getblockcount", "") + | ||||
HelpExampleRpc("getblockcount", "")}, | HelpExampleRpc("getblockcount", "")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return ::ChainActive().Height(); | return EnsureChainman(request.context).ActiveHeight(); | ||||
}, | }, | ||||
}; | }; | ||||
} | } | ||||
static RPCHelpMan getbestblockhash() { | static RPCHelpMan getbestblockhash() { | ||||
return RPCHelpMan{ | return RPCHelpMan{ | ||||
"getbestblockhash", | "getbestblockhash", | ||||
"Returns the hash of the best (tip) block in the " | "Returns the hash of the best (tip) block in the " | ||||
"most-work fully-validated chain.\n", | "most-work fully-validated chain.\n", | ||||
{}, | {}, | ||||
RPCResult{RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"}, | RPCResult{RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"}, | ||||
RPCExamples{HelpExampleCli("getbestblockhash", "") + | RPCExamples{HelpExampleCli("getbestblockhash", "") + | ||||
HelpExampleRpc("getbestblockhash", "")}, | HelpExampleRpc("getbestblockhash", "")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return ::ChainActive().Tip()->GetBlockHash().GetHex(); | return EnsureChainman(request.context) | ||||
.ActiveTip() | |||||
->GetBlockHash() | |||||
.GetHex(); | |||||
}, | }, | ||||
}; | }; | ||||
} | } | ||||
RPCHelpMan getfinalizedblockhash() { | RPCHelpMan getfinalizedblockhash() { | ||||
return RPCHelpMan{ | return RPCHelpMan{ | ||||
"getfinalizedblockhash", | "getfinalizedblockhash", | ||||
"Returns the hash of the currently finalized block\n", | "Returns the hash of the currently finalized block\n", | ||||
{}, | {}, | ||||
RPCResult{RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"}, | RPCResult{RPCResult::Type::STR_HEX, "", "the block hash, hex-encoded"}, | ||||
RPCExamples{HelpExampleCli("getfinalizedblockhash", "") + | RPCExamples{HelpExampleCli("getfinalizedblockhash", "") + | ||||
HelpExampleRpc("getfinalizedblockhash", "")}, | HelpExampleRpc("getfinalizedblockhash", "")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CChainState &active_chainstate = | |||||
EnsureChainman(request.context).ActiveChainstate(); | |||||
const CBlockIndex *blockIndexFinalized = | const CBlockIndex *blockIndexFinalized = | ||||
::ChainstateActive().GetFinalizedBlock(); | active_chainstate.GetFinalizedBlock(); | ||||
if (blockIndexFinalized) { | if (blockIndexFinalized) { | ||||
return blockIndexFinalized->GetBlockHash().GetHex(); | return blockIndexFinalized->GetBlockHash().GetHex(); | ||||
} | } | ||||
return UniValue(UniValue::VSTR); | return UniValue(UniValue::VSTR); | ||||
}, | }, | ||||
}; | }; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 211 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
RPCResult{RPCResult::Type::NUM, "", | RPCResult{RPCResult::Type::NUM, "", | ||||
"the proof-of-work difficulty as a multiple of the minimum " | "the proof-of-work difficulty as a multiple of the minimum " | ||||
"difficulty."}, | "difficulty."}, | ||||
RPCExamples{HelpExampleCli("getdifficulty", "") + | RPCExamples{HelpExampleCli("getdifficulty", "") + | ||||
HelpExampleRpc("getdifficulty", "")}, | HelpExampleRpc("getdifficulty", "")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return GetDifficulty(::ChainActive().Tip()); | return GetDifficulty(EnsureChainman(request.context).ActiveTip()); | ||||
}, | }, | ||||
}; | }; | ||||
} | } | ||||
static std::vector<RPCResult> MempoolEntryDescription() { | static std::vector<RPCResult> MempoolEntryDescription() { | ||||
const auto &ticker = Currency::get().ticker; | const auto &ticker = Currency::get().ticker; | ||||
return { | return { | ||||
RPCResult{RPCResult::Type::NUM, "size", "transaction size."}, | RPCResult{RPCResult::Type::NUM, "size", "transaction size."}, | ||||
▲ Show 20 Lines • Show All 411 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
"The height index"}, | "The height index"}, | ||||
}, | }, | ||||
RPCResult{RPCResult::Type::STR_HEX, "", "The block hash"}, | RPCResult{RPCResult::Type::STR_HEX, "", "The block hash"}, | ||||
RPCExamples{HelpExampleCli("getblockhash", "1000") + | RPCExamples{HelpExampleCli("getblockhash", "1000") + | ||||
HelpExampleRpc("getblockhash", "1000")}, | HelpExampleRpc("getblockhash", "1000")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const CChain &active_chain = | |||||
EnsureChainman(request.context).ActiveChain(); | |||||
int nHeight = request.params[0].get_int(); | int nHeight = request.params[0].get_int(); | ||||
if (nHeight < 0 || nHeight > ::ChainActive().Height()) { | if (nHeight < 0 || nHeight > active_chain.Height()) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"Block height out of range"); | "Block height out of range"); | ||||
} | } | ||||
CBlockIndex *pblockindex = ::ChainActive()[nHeight]; | CBlockIndex *pblockindex = active_chain[nHeight]; | ||||
return pblockindex->GetBlockHash().GetHex(); | return pblockindex->GetBlockHash().GetHex(); | ||||
}, | }, | ||||
}; | }; | ||||
} | } | ||||
static RPCHelpMan getblockheader() { | static RPCHelpMan getblockheader() { | ||||
return RPCHelpMan{ | return RPCHelpMan{ | ||||
"getblockheader", | "getblockheader", | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
if (!request.params[1].isNull()) { | 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 = g_chainman.m_blockman.LookupBlockIndex(hash); | ChainstateManager &chainman = EnsureChainman(request.context); | ||||
tip = ::ChainActive().Tip(); | pblockindex = chainman.m_blockman.LookupBlockIndex(hash); | ||||
tip = chainman.ActiveTip(); | |||||
} | } | ||||
if (!pblockindex) { | if (!pblockindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Block not found"); | "Block not found"); | ||||
} | } | ||||
if (!fVerbose) { | if (!fVerbose) { | ||||
▲ Show 20 Lines • Show All 142 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
} | } | ||||
} | } | ||||
CBlock block; | CBlock block; | ||||
const CBlockIndex *pblockindex; | const CBlockIndex *pblockindex; | ||||
const CBlockIndex *tip; | const CBlockIndex *tip; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash); | ChainstateManager &chainman = EnsureChainman(request.context); | ||||
tip = ::ChainActive().Tip(); | pblockindex = chainman.m_blockman.LookupBlockIndex(hash); | ||||
tip = chainman.ActiveTip(); | |||||
if (!pblockindex) { | if (!pblockindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Block not found"); | "Block not found"); | ||||
} | } | ||||
block = GetBlockChecked(config, pblockindex); | block = GetBlockChecked(config, pblockindex); | ||||
} | } | ||||
Show All 31 Lines | return RPCHelpMan{ | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
if (!fPruneMode) { | if (!fPruneMode) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_MISC_ERROR, | RPC_MISC_ERROR, | ||||
"Cannot prune blocks because node is not in prune mode."); | "Cannot prune blocks because node is not in prune mode."); | ||||
} | } | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
ChainstateManager &chainman = EnsureChainman(request.context); | |||||
int heightParam = request.params[0].get_int(); | int heightParam = request.params[0].get_int(); | ||||
if (heightParam < 0) { | if (heightParam < 0) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"Negative block height."); | "Negative block height."); | ||||
} | } | ||||
// Height value more than a billion is too high to be a block | // 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 | // height, and too low to be a block time (corresponds to timestamp | ||||
// from Sep 2001). | // from Sep 2001). | ||||
if (heightParam > 1000000000) { | if (heightParam > 1000000000) { | ||||
// Add a 2 hour buffer to include blocks which might have had | // Add a 2 hour buffer to include blocks which might have had | ||||
// old timestamps | // old timestamps | ||||
CBlockIndex *pindex = ::ChainActive().FindEarliestAtLeast( | CBlockIndex *pindex = | ||||
chainman.ActiveChain().FindEarliestAtLeast( | |||||
heightParam - TIMESTAMP_WINDOW, 0); | heightParam - TIMESTAMP_WINDOW, 0); | ||||
if (!pindex) { | if (!pindex) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"Could not find block with at least the " | "Could not find block with at least the " | ||||
"specified timestamp."); | "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)chainman.ActiveHeight(); | ||||
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) { | ||||
LogPrint(BCLog::RPC, | LogPrint(BCLog::RPC, | ||||
"Attempt to prune blocks close to the tip. " | "Attempt to prune blocks close to the tip. " | ||||
"Retaining the minimum number of blocks.\n"); | "Retaining the minimum number of blocks.\n"); | ||||
height = chainHeight - MIN_BLOCKS_TO_KEEP; | height = chainHeight - MIN_BLOCKS_TO_KEEP; | ||||
} | } | ||||
PruneBlockFilesManual(::ChainstateActive(), height); | PruneBlockFilesManual(chainman.ActiveChainstate(), height); | ||||
const CBlockIndex *block = ::ChainActive().Tip(); | const CBlockIndex *block = chainman.ActiveTip(); | ||||
CHECK_NONFATAL(block); | CHECK_NONFATAL(block); | ||||
while (block->pprev && (block->pprev->nStatus.hasData())) { | while (block->pprev && (block->pprev->nStatus.hasData())) { | ||||
block = block->pprev; | block = block->pprev; | ||||
} | } | ||||
return uint64_t(block->nHeight); | return uint64_t(block->nHeight); | ||||
}, | }, | ||||
}; | }; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
}}, | }}, | ||||
RPCExamples{HelpExampleCli("gettxoutsetinfo", "") + | RPCExamples{HelpExampleCli("gettxoutsetinfo", "") + | ||||
HelpExampleRpc("gettxoutsetinfo", "")}, | HelpExampleRpc("gettxoutsetinfo", "")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
UniValue ret(UniValue::VOBJ); | UniValue ret(UniValue::VOBJ); | ||||
CCoinsStats stats; | CCoinsStats stats; | ||||
::ChainstateActive().ForceFlushStateToDisk(); | CChainState &active_chainstate = | ||||
EnsureChainman(request.context).ActiveChainstate(); | |||||
active_chainstate.ForceFlushStateToDisk(); | |||||
const CoinStatsHashType hash_type{ | const CoinStatsHashType hash_type{ | ||||
request.params[0].isNull() | request.params[0].isNull() | ||||
? CoinStatsHashType::HASH_SERIALIZED | ? CoinStatsHashType::HASH_SERIALIZED | ||||
: ParseHashType(request.params[0].get_str())}; | : ParseHashType(request.params[0].get_str())}; | ||||
CCoinsView *coins_view = | CCoinsView *coins_view; | ||||
WITH_LOCK(::cs_main, return &::ChainstateActive().CoinsDB()); | BlockManager *blockman; | ||||
{ | |||||
LOCK(::cs_main); | |||||
coins_view = &active_chainstate.CoinsDB(); | |||||
blockman = &active_chainstate.m_blockman; | |||||
} | |||||
NodeContext &node = EnsureNodeContext(request.context); | NodeContext &node = EnsureNodeContext(request.context); | ||||
if (GetUTXOStats(coins_view, | if (GetUTXOStats(coins_view, *blockman, stats, hash_type, | ||||
WITH_LOCK(::cs_main, | node.rpc_interruption_point)) { | ||||
return std::ref(g_chainman.m_blockman)), | |||||
stats, hash_type, node.rpc_interruption_point)) { | |||||
ret.pushKV("height", int64_t(stats.nHeight)); | ret.pushKV("height", int64_t(stats.nHeight)); | ||||
ret.pushKV("bestblock", stats.hashBlock.GetHex()); | ret.pushKV("bestblock", stats.hashBlock.GetHex()); | ||||
ret.pushKV("transactions", int64_t(stats.nTransactions)); | ret.pushKV("transactions", int64_t(stats.nTransactions)); | ||||
ret.pushKV("txouts", int64_t(stats.nTransactionOutputs)); | ret.pushKV("txouts", int64_t(stats.nTransactionOutputs)); | ||||
ret.pushKV("bogosize", int64_t(stats.nBogoSize)); | ret.pushKV("bogosize", int64_t(stats.nBogoSize)); | ||||
if (hash_type == CoinStatsHashType::HASH_SERIALIZED) { | if (hash_type == CoinStatsHashType::HASH_SERIALIZED) { | ||||
ret.pushKV("hash_serialized", | ret.pushKV("hash_serialized", | ||||
stats.hashSerialized.GetHex()); | stats.hashSerialized.GetHex()); | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
int n = request.params[1].get_int(); | int n = request.params[1].get_int(); | ||||
COutPoint out(txid, n); | COutPoint out(txid, n); | ||||
bool fMempool = true; | bool fMempool = true; | ||||
if (!request.params[2].isNull()) { | if (!request.params[2].isNull()) { | ||||
fMempool = request.params[2].get_bool(); | fMempool = request.params[2].get_bool(); | ||||
} | } | ||||
Coin coin; | Coin coin; | ||||
CCoinsViewCache *coins_view = &::ChainstateActive().CoinsTip(); | CChainState &active_chainstate = | ||||
EnsureChainman(request.context).ActiveChainstate(); | |||||
CCoinsViewCache *coins_view = &active_chainstate.CoinsTip(); | |||||
if (fMempool) { | if (fMempool) { | ||||
const CTxMemPool &mempool = EnsureMemPool(request.context); | const CTxMemPool &mempool = EnsureMemPool(request.context); | ||||
LOCK(mempool.cs); | LOCK(mempool.cs); | ||||
CCoinsViewMemPool view(coins_view, mempool); | CCoinsViewMemPool view(coins_view, mempool); | ||||
if (!view.GetCoin(out, coin) || mempool.isSpent(out)) { | if (!view.GetCoin(out, coin) || mempool.isSpent(out)) { | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
} else { | } else { | ||||
if (!coins_view->GetCoin(out, coin)) { | if (!coins_view->GetCoin(out, coin)) { | ||||
return NullUniValue; | return NullUniValue; | ||||
} | } | ||||
} | } | ||||
const CBlockIndex *pindex = g_chainman.m_blockman.LookupBlockIndex( | const CBlockIndex *pindex = | ||||
active_chainstate.m_blockman.LookupBlockIndex( | |||||
coins_view->GetBestBlock()); | coins_view->GetBestBlock()); | ||||
ret.pushKV("bestblock", pindex->GetBlockHash().GetHex()); | ret.pushKV("bestblock", pindex->GetBlockHash().GetHex()); | ||||
if (coin.GetHeight() == MEMPOOL_HEIGHT) { | if (coin.GetHeight() == MEMPOOL_HEIGHT) { | ||||
ret.pushKV("confirmations", 0); | ret.pushKV("confirmations", 0); | ||||
} else { | } else { | ||||
ret.pushKV("confirmations", | ret.pushKV("confirmations", | ||||
int64_t(pindex->nHeight - coin.GetHeight() + 1)); | int64_t(pindex->nHeight - coin.GetHeight() + 1)); | ||||
} | } | ||||
ret.pushKV("value", coin.GetTxOut().nValue); | ret.pushKV("value", coin.GetTxOut().nValue); | ||||
Show All 29 Lines | return RPCHelpMan{ | ||||
? DEFAULT_CHECKLEVEL | ? DEFAULT_CHECKLEVEL | ||||
: request.params[0].get_int()); | : request.params[0].get_int()); | ||||
const int check_depth{request.params[1].isNull() | const int check_depth{request.params[1].isNull() | ||||
? DEFAULT_CHECKBLOCKS | ? DEFAULT_CHECKBLOCKS | ||||
: request.params[1].get_int()}; | : request.params[1].get_int()}; | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
return CVerifyDB().VerifyDB(::ChainstateActive(), config, | CChainState &active_chainstate = | ||||
::ChainstateActive().CoinsTip(), | EnsureChainman(request.context).ActiveChainstate(); | ||||
return CVerifyDB().VerifyDB(active_chainstate, config, | |||||
active_chainstate.CoinsTip(), | |||||
check_level, check_depth); | check_level, check_depth); | ||||
}, | }, | ||||
}; | }; | ||||
} | } | ||||
static void BIP9SoftForkDescPushBack(UniValue &softforks, | static void BIP9SoftForkDescPushBack(const CBlockIndex *active_chain_tip, | ||||
UniValue &softforks, | |||||
const Consensus::Params &consensusParams, | const Consensus::Params &consensusParams, | ||||
Consensus::DeploymentPos id) | Consensus::DeploymentPos id) | ||||
EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | EXCLUSIVE_LOCKS_REQUIRED(cs_main) { | ||||
// For BIP9 deployments. | // For BIP9 deployments. | ||||
// Deployments (e.g. testdummy) with timeout value before Jan 1, 2009 are | // Deployments (e.g. testdummy) with timeout value before Jan 1, 2009 are | ||||
// hidden. A timeout value of 0 guarantees a softfork will never be | // hidden. A timeout value of 0 guarantees a softfork will never be | ||||
// activated. This is used when merging logic to implement a proposed | // activated. This is used when merging logic to implement a proposed | ||||
// softfork without a specified deployment schedule. | // softfork without a specified deployment schedule. | ||||
if (consensusParams.vDeployments[id].nTimeout <= 1230768000) { | if (consensusParams.vDeployments[id].nTimeout <= 1230768000) { | ||||
return; | return; | ||||
} | } | ||||
UniValue bip9(UniValue::VOBJ); | UniValue bip9(UniValue::VOBJ); | ||||
const ThresholdState thresholdState = VersionBitsState( | const ThresholdState thresholdState = VersionBitsState( | ||||
::ChainActive().Tip(), consensusParams, id, versionbitscache); | active_chain_tip, consensusParams, id, versionbitscache); | ||||
switch (thresholdState) { | switch (thresholdState) { | ||||
case ThresholdState::DEFINED: | case ThresholdState::DEFINED: | ||||
bip9.pushKV("status", "defined"); | bip9.pushKV("status", "defined"); | ||||
break; | break; | ||||
case ThresholdState::STARTED: | case ThresholdState::STARTED: | ||||
bip9.pushKV("status", "started"); | bip9.pushKV("status", "started"); | ||||
break; | break; | ||||
case ThresholdState::LOCKED_IN: | case ThresholdState::LOCKED_IN: | ||||
bip9.pushKV("status", "locked_in"); | bip9.pushKV("status", "locked_in"); | ||||
break; | break; | ||||
case ThresholdState::ACTIVE: | case ThresholdState::ACTIVE: | ||||
bip9.pushKV("status", "active"); | bip9.pushKV("status", "active"); | ||||
break; | break; | ||||
case ThresholdState::FAILED: | case ThresholdState::FAILED: | ||||
bip9.pushKV("status", "failed"); | bip9.pushKV("status", "failed"); | ||||
break; | break; | ||||
} | } | ||||
if (ThresholdState::STARTED == thresholdState) { | if (ThresholdState::STARTED == thresholdState) { | ||||
bip9.pushKV("bit", consensusParams.vDeployments[id].bit); | bip9.pushKV("bit", consensusParams.vDeployments[id].bit); | ||||
} | } | ||||
bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime); | bip9.pushKV("start_time", consensusParams.vDeployments[id].nStartTime); | ||||
bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout); | bip9.pushKV("timeout", consensusParams.vDeployments[id].nTimeout); | ||||
int64_t since_height = VersionBitsStateSinceHeight( | int64_t since_height = VersionBitsStateSinceHeight( | ||||
::ChainActive().Tip(), consensusParams, id, versionbitscache); | active_chain_tip, consensusParams, id, versionbitscache); | ||||
bip9.pushKV("since", since_height); | bip9.pushKV("since", since_height); | ||||
if (ThresholdState::STARTED == thresholdState) { | if (ThresholdState::STARTED == thresholdState) { | ||||
UniValue statsUV(UniValue::VOBJ); | UniValue statsUV(UniValue::VOBJ); | ||||
BIP9Stats statsStruct = | BIP9Stats statsStruct = | ||||
VersionBitsStatistics(::ChainActive().Tip(), consensusParams, id); | VersionBitsStatistics(active_chain_tip, consensusParams, id); | ||||
statsUV.pushKV("period", statsStruct.period); | statsUV.pushKV("period", statsStruct.period); | ||||
statsUV.pushKV("threshold", statsStruct.threshold); | statsUV.pushKV("threshold", statsStruct.threshold); | ||||
statsUV.pushKV("elapsed", statsStruct.elapsed); | statsUV.pushKV("elapsed", statsStruct.elapsed); | ||||
statsUV.pushKV("count", statsStruct.count); | statsUV.pushKV("count", statsStruct.count); | ||||
statsUV.pushKV("possible", statsStruct.possible); | statsUV.pushKV("possible", statsStruct.possible); | ||||
bip9.pushKV("statistics", statsUV); | bip9.pushKV("statistics", statsUV); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 121 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
RPCExamples{HelpExampleCli("getblockchaininfo", "") + | RPCExamples{HelpExampleCli("getblockchaininfo", "") + | ||||
HelpExampleRpc("getblockchaininfo", "")}, | HelpExampleRpc("getblockchaininfo", "")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
const CChainParams &chainparams = config.GetChainParams(); | const CChainParams &chainparams = config.GetChainParams(); | ||||
const CBlockIndex *tip = ::ChainActive().Tip(); | ChainstateManager &chainman = EnsureChainman(request.context); | ||||
const CBlockIndex *tip = chainman.ActiveTip(); | |||||
CHECK_NONFATAL(tip); | |||||
const int height = tip->nHeight; | |||||
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", height); | ||||
obj.pushKV("headers", | obj.pushKV("headers", | ||||
pindexBestHeader ? pindexBestHeader->nHeight : -1); | 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", | obj.pushKV("initialblockdownload", | ||||
::ChainstateActive().IsInitialBlockDownload()); | chainman.ActiveChainstate().IsInitialBlockDownload()); | ||||
obj.pushKV("chainwork", tip->nChainWork.GetHex()); | obj.pushKV("chainwork", tip->nChainWork.GetHex()); | ||||
obj.pushKV("size_on_disk", CalculateCurrentUsage()); | obj.pushKV("size_on_disk", CalculateCurrentUsage()); | ||||
obj.pushKV("pruned", fPruneMode); | obj.pushKV("pruned", fPruneMode); | ||||
if (fPruneMode) { | if (fPruneMode) { | ||||
const CBlockIndex *block = tip; | const CBlockIndex *block = tip; | ||||
CHECK_NONFATAL(block); | CHECK_NONFATAL(block); | ||||
while (block->pprev && (block->pprev->nStatus.hasData())) { | while (block->pprev && (block->pprev->nStatus.hasData())) { | ||||
block = block->pprev; | block = block->pprev; | ||||
} | } | ||||
obj.pushKV("pruneheight", block->nHeight); | obj.pushKV("pruneheight", block->nHeight); | ||||
// if 0, execution bypasses the whole if block. | // if 0, execution bypasses the whole if block. | ||||
bool automatic_pruning = (gArgs.GetArg("-prune", 0) != 1); | bool automatic_pruning = (gArgs.GetArg("-prune", 0) != 1); | ||||
obj.pushKV("automatic_pruning", automatic_pruning); | obj.pushKV("automatic_pruning", automatic_pruning); | ||||
if (automatic_pruning) { | if (automatic_pruning) { | ||||
obj.pushKV("prune_target_size", nPruneTarget); | obj.pushKV("prune_target_size", nPruneTarget); | ||||
} | } | ||||
} | } | ||||
UniValue softforks(UniValue::VOBJ); | UniValue softforks(UniValue::VOBJ); | ||||
for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; | for (int i = 0; i < (int)Consensus::MAX_VERSION_BITS_DEPLOYMENTS; | ||||
i++) { | i++) { | ||||
BIP9SoftForkDescPushBack(softforks, chainparams.GetConsensus(), | BIP9SoftForkDescPushBack(tip, softforks, | ||||
chainparams.GetConsensus(), | |||||
Consensus::DeploymentPos(i)); | Consensus::DeploymentPos(i)); | ||||
} | } | ||||
obj.pushKV("softforks", softforks); | obj.pushKV("softforks", softforks); | ||||
obj.pushKV("warnings", GetWarnings(false).original); | obj.pushKV("warnings", GetWarnings(false).original); | ||||
return obj; | return obj; | ||||
}, | }, | ||||
}; | }; | ||||
▲ Show 20 Lines • Show All 209 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
RPCResult{RPCResult::Type::NONE, "", ""}, | RPCResult{RPCResult::Type::NONE, "", ""}, | ||||
RPCExamples{HelpExampleCli("preciousblock", "\"blockhash\"") + | RPCExamples{HelpExampleCli("preciousblock", "\"blockhash\"") + | ||||
HelpExampleRpc("preciousblock", "\"blockhash\"")}, | HelpExampleRpc("preciousblock", "\"blockhash\"")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
BlockHash hash(ParseHashV(request.params[0], "blockhash")); | BlockHash hash(ParseHashV(request.params[0], "blockhash")); | ||||
CBlockIndex *pblockindex; | CBlockIndex *pblockindex; | ||||
ChainstateManager &chainman = EnsureChainman(request.context); | |||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash); | pblockindex = chainman.m_blockman.LookupBlockIndex(hash); | ||||
if (!pblockindex) { | if (!pblockindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Block not found"); | "Block not found"); | ||||
} | } | ||||
} | } | ||||
BlockValidationState state; | BlockValidationState state; | ||||
::ChainstateActive().PreciousBlock(config, state, pblockindex); | chainman.ActiveChainstate().PreciousBlock(config, state, | ||||
pblockindex); | |||||
if (!state.IsValid()) { | if (!state.IsValid()) { | ||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); | throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
}, | }, | ||||
}; | }; | ||||
Show All 14 Lines | return RPCHelpMan{ | ||||
RPCExamples{HelpExampleCli("finalizeblock", "\"blockhash\"") + | RPCExamples{HelpExampleCli("finalizeblock", "\"blockhash\"") + | ||||
HelpExampleRpc("finalizeblock", "\"blockhash\"")}, | HelpExampleRpc("finalizeblock", "\"blockhash\"")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
std::string strHash = request.params[0].get_str(); | std::string strHash = request.params[0].get_str(); | ||||
BlockHash hash(uint256S(strHash)); | BlockHash hash(uint256S(strHash)); | ||||
BlockValidationState state; | BlockValidationState state; | ||||
ChainstateManager &chainman = EnsureChainman(request.context); | |||||
CBlockIndex *pblockindex = nullptr; | CBlockIndex *pblockindex = nullptr; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash); | pblockindex = chainman.m_blockman.LookupBlockIndex(hash); | ||||
if (!pblockindex) { | if (!pblockindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Block not found"); | "Block not found"); | ||||
} | } | ||||
} // end of locked cs_main scope | } // end of locked cs_main scope | ||||
::ChainstateActive().FinalizeBlock(config, state, pblockindex); | chainman.ActiveChainstate().FinalizeBlock(config, state, | ||||
pblockindex); | |||||
if (state.IsValid()) { | if (state.IsValid()) { | ||||
::ChainstateActive().ActivateBestChain(config, state); | chainman.ActiveChainstate().ActivateBestChain(config, state); | ||||
} | } | ||||
if (!state.IsValid()) { | if (!state.IsValid()) { | ||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString()); | throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString()); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
}, | }, | ||||
Show All 12 Lines | return RPCHelpMan{ | ||||
RPCResult{RPCResult::Type::NONE, "", ""}, | RPCResult{RPCResult::Type::NONE, "", ""}, | ||||
RPCExamples{HelpExampleCli("invalidateblock", "\"blockhash\"") + | RPCExamples{HelpExampleCli("invalidateblock", "\"blockhash\"") + | ||||
HelpExampleRpc("invalidateblock", "\"blockhash\"")}, | HelpExampleRpc("invalidateblock", "\"blockhash\"")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
const BlockHash hash(ParseHashV(request.params[0], "blockhash")); | const BlockHash hash(ParseHashV(request.params[0], "blockhash")); | ||||
BlockValidationState state; | BlockValidationState state; | ||||
ChainstateManager &chainman = EnsureChainman(request.context); | |||||
CBlockIndex *pblockindex; | CBlockIndex *pblockindex; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash); | pblockindex = chainman.m_blockman.LookupBlockIndex(hash); | ||||
if (!pblockindex) { | if (!pblockindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Block not found"); | "Block not found"); | ||||
} | } | ||||
} | } | ||||
::ChainstateActive().InvalidateBlock(config, state, pblockindex); | chainman.ActiveChainstate().InvalidateBlock(config, state, | ||||
pblockindex); | |||||
if (state.IsValid()) { | if (state.IsValid()) { | ||||
::ChainstateActive().ActivateBestChain(config, state); | chainman.ActiveChainstate().ActivateBestChain(config, state); | ||||
} | } | ||||
if (!state.IsValid()) { | if (!state.IsValid()) { | ||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString()); | throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString()); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
}, | }, | ||||
Show All 12 Lines | return RPCHelpMan{ | ||||
RPCExamples{HelpExampleCli("parkblock", "\"blockhash\"") + | RPCExamples{HelpExampleCli("parkblock", "\"blockhash\"") + | ||||
HelpExampleRpc("parkblock", "\"blockhash\"")}, | HelpExampleRpc("parkblock", "\"blockhash\"")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
const std::string strHash = request.params[0].get_str(); | const std::string strHash = request.params[0].get_str(); | ||||
const BlockHash hash(uint256S(strHash)); | const BlockHash hash(uint256S(strHash)); | ||||
BlockValidationState state; | BlockValidationState state; | ||||
ChainstateManager &chainman = EnsureChainman(request.context); | |||||
CBlockIndex *pblockindex = nullptr; | CBlockIndex *pblockindex = nullptr; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pblockindex = g_chainman.m_blockman.LookupBlockIndex(hash); | pblockindex = chainman.m_blockman.LookupBlockIndex(hash); | ||||
if (!pblockindex) { | if (!pblockindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Block not found"); | "Block not found"); | ||||
} | } | ||||
} | } | ||||
::ChainstateActive().ParkBlock(config, state, pblockindex); | chainman.ActiveChainstate().ParkBlock(config, state, pblockindex); | ||||
if (state.IsValid()) { | if (state.IsValid()) { | ||||
::ChainstateActive().ActivateBestChain(config, state); | chainman.ActiveChainstate().ActivateBestChain(config, state); | ||||
} | } | ||||
if (!state.IsValid()) { | if (!state.IsValid()) { | ||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); | throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
}, | }, | ||||
Show All 10 Lines | return RPCHelpMan{ | ||||
{"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | {"blockhash", RPCArg::Type::STR_HEX, RPCArg::Optional::NO, | ||||
"the hash of the block to reconsider"}, | "the hash of the block to reconsider"}, | ||||
}, | }, | ||||
RPCResult{RPCResult::Type::NONE, "", ""}, | RPCResult{RPCResult::Type::NONE, "", ""}, | ||||
RPCExamples{HelpExampleCli("reconsiderblock", "\"blockhash\"") + | RPCExamples{HelpExampleCli("reconsiderblock", "\"blockhash\"") + | ||||
HelpExampleRpc("reconsiderblock", "\"blockhash\"")}, | HelpExampleRpc("reconsiderblock", "\"blockhash\"")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
ChainstateManager &chainman = EnsureChainman(request.context); | |||||
const BlockHash hash(ParseHashV(request.params[0], "blockhash")); | const BlockHash hash(ParseHashV(request.params[0], "blockhash")); | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CBlockIndex *pblockindex = | CBlockIndex *pblockindex = | ||||
g_chainman.m_blockman.LookupBlockIndex(hash); | chainman.m_blockman.LookupBlockIndex(hash); | ||||
if (!pblockindex) { | if (!pblockindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Block not found"); | "Block not found"); | ||||
} | } | ||||
::ChainstateActive().ResetBlockFailureFlags(pblockindex); | chainman.ActiveChainstate().ResetBlockFailureFlags(pblockindex); | ||||
} | } | ||||
BlockValidationState state; | BlockValidationState state; | ||||
::ChainstateActive().ActivateBestChain(config, state); | chainman.ActiveChainstate().ActivateBestChain(config, state); | ||||
if (!state.IsValid()) { | if (!state.IsValid()) { | ||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString()); | throw JSONRPCError(RPC_DATABASE_ERROR, state.ToString()); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
}, | }, | ||||
}; | }; | ||||
Show All 10 Lines | return RPCHelpMan{ | ||||
"the hash of the block to unpark"}, | "the hash of the block to unpark"}, | ||||
}, | }, | ||||
RPCResult{RPCResult::Type::NONE, "", ""}, | RPCResult{RPCResult::Type::NONE, "", ""}, | ||||
RPCExamples{HelpExampleCli("unparkblock", "\"blockhash\"") + | RPCExamples{HelpExampleCli("unparkblock", "\"blockhash\"") + | ||||
HelpExampleRpc("unparkblock", "\"blockhash\"")}, | HelpExampleRpc("unparkblock", "\"blockhash\"")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
const std::string strHash = request.params[0].get_str(); | const std::string strHash = request.params[0].get_str(); | ||||
ChainstateManager &chainman = EnsureChainman(request.context); | |||||
const BlockHash hash(uint256S(strHash)); | const BlockHash hash(uint256S(strHash)); | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
CBlockIndex *pblockindex = | CBlockIndex *pblockindex = | ||||
g_chainman.m_blockman.LookupBlockIndex(hash); | chainman.m_blockman.LookupBlockIndex(hash); | ||||
if (!pblockindex) { | if (!pblockindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Block not found"); | "Block not found"); | ||||
} | } | ||||
::ChainstateActive().UnparkBlockAndChildren(pblockindex); | chainman.ActiveChainstate().UnparkBlockAndChildren(pblockindex); | ||||
} | } | ||||
BlockValidationState state; | BlockValidationState state; | ||||
::ChainstateActive().ActivateBestChain(config, state); | chainman.ActiveChainstate().ActivateBestChain(config, state); | ||||
if (!state.IsValid()) { | if (!state.IsValid()) { | ||||
throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); | throw JSONRPCError(RPC_DATABASE_ERROR, state.GetRejectReason()); | ||||
} | } | ||||
return NullUniValue; | return NullUniValue; | ||||
}, | }, | ||||
}; | }; | ||||
Show All 36 Lines | return RPCHelpMan{ | ||||
{RPCResult::Type::NUM, "txrate", | {RPCResult::Type::NUM, "txrate", | ||||
"The average rate of transactions per second in the " | "The average rate of transactions per second in the " | ||||
"window. Only returned if \"window_interval\" is > 0"}, | "window. Only returned if \"window_interval\" is > 0"}, | ||||
}}, | }}, | ||||
RPCExamples{HelpExampleCli("getchaintxstats", "") + | RPCExamples{HelpExampleCli("getchaintxstats", "") + | ||||
HelpExampleRpc("getchaintxstats", "2016")}, | HelpExampleRpc("getchaintxstats", "2016")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
ChainstateManager &chainman = EnsureChainman(request.context); | |||||
const CBlockIndex *pindex; | const CBlockIndex *pindex; | ||||
// By default: 1 month | // By default: 1 month | ||||
int blockcount = | int blockcount = | ||||
30 * 24 * 60 * 60 / | 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 = chainman.ActiveTip(); | ||||
} else { | } else { | ||||
BlockHash hash(ParseHashV(request.params[1], "blockhash")); | BlockHash hash(ParseHashV(request.params[1], "blockhash")); | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
pindex = g_chainman.m_blockman.LookupBlockIndex(hash); | pindex = chainman.m_blockman.LookupBlockIndex(hash); | ||||
if (!pindex) { | if (!pindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Block not found"); | "Block not found"); | ||||
} | } | ||||
if (!::ChainActive().Contains(pindex)) { | if (!chainman.ActiveChain().Contains(pindex)) { | ||||
throw JSONRPCError(RPC_INVALID_PARAMETER, | throw JSONRPCError(RPC_INVALID_PARAMETER, | ||||
"Block is not in main chain"); | "Block is not in main chain"); | ||||
} | } | ||||
} | } | ||||
CHECK_NONFATAL(pindex != nullptr); | CHECK_NONFATAL(pindex != nullptr); | ||||
if (request.params[0].isNull()) { | if (request.params[0].isNull()) { | ||||
▲ Show 20 Lines • Show All 150 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
HelpExampleRpc( | HelpExampleRpc( | ||||
"getblockstats", | "getblockstats", | ||||
R"("00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09", ["minfeerate","avgfeerate"])") + | R"("00000000c937983704a73af28acdec37b049d214adbda81d7e2a3dd146f6ed09", ["minfeerate","avgfeerate"])") + | ||||
HelpExampleRpc("getblockstats", | HelpExampleRpc("getblockstats", | ||||
R"(1000, ["minfeerate","avgfeerate"])")}, | R"(1000, ["minfeerate","avgfeerate"])")}, | ||||
[&](const RPCHelpMan &self, const Config &config, | [&](const RPCHelpMan &self, const Config &config, | ||||
const JSONRPCRequest &request) -> UniValue { | const JSONRPCRequest &request) -> UniValue { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
ChainstateManager &chainman = EnsureChainman(request.context); | |||||
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 = chainman.ActiveHeight(); | ||||
if (height < 0) { | if (height < 0) { | ||||
throw JSONRPCError( | throw JSONRPCError( | ||||
RPC_INVALID_PARAMETER, | RPC_INVALID_PARAMETER, | ||||
strprintf("Target block height %d is negative", | strprintf("Target block height %d is negative", | ||||
height)); | 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", | strprintf("Target block height %d after current tip %d", | ||||
height, current_tip)); | height, current_tip)); | ||||
} | } | ||||
pindex = ::ChainActive()[height]; | pindex = chainman.ActiveChain()[height]; | ||||
} else { | } else { | ||||
const BlockHash hash( | const BlockHash hash( | ||||
ParseHashV(request.params[0], "hash_or_height")); | ParseHashV(request.params[0], "hash_or_height")); | ||||
pindex = g_chainman.m_blockman.LookupBlockIndex(hash); | pindex = chainman.m_blockman.LookupBlockIndex(hash); | ||||
if (!pindex) { | if (!pindex) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Block not found"); | "Block not found"); | ||||
} | } | ||||
if (!::ChainActive().Contains(pindex)) { | if (!chainman.ActiveChain().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())); | ||||
} | } | ||||
} | } | ||||
CHECK_NONFATAL(pindex != nullptr); | CHECK_NONFATAL(pindex != nullptr); | ||||
▲ Show 20 Lines • Show All 439 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
std::map<COutPoint, Coin> coins; | std::map<COutPoint, Coin> coins; | ||||
g_should_abort_scan = false; | g_should_abort_scan = false; | ||||
g_scan_progress = 0; | g_scan_progress = 0; | ||||
int64_t count = 0; | int64_t count = 0; | ||||
std::unique_ptr<CCoinsViewCursor> pcursor; | std::unique_ptr<CCoinsViewCursor> pcursor; | ||||
CBlockIndex *tip; | CBlockIndex *tip; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
::ChainstateActive().ForceFlushStateToDisk(); | ChainstateManager &chainman = | ||||
EnsureChainman(request.context); | |||||
chainman.ActiveChainstate().ForceFlushStateToDisk(); | |||||
pcursor = std::unique_ptr<CCoinsViewCursor>( | pcursor = std::unique_ptr<CCoinsViewCursor>( | ||||
::ChainstateActive().CoinsDB().Cursor()); | chainman.ActiveChainstate().CoinsDB().Cursor()); | ||||
CHECK_NONFATAL(pcursor); | CHECK_NONFATAL(pcursor); | ||||
tip = ::ChainActive().Tip(); | tip = chainman.ActiveTip(); | ||||
CHECK_NONFATAL(tip); | CHECK_NONFATAL(tip); | ||||
} | } | ||||
NodeContext &node = EnsureNodeContext(request.context); | NodeContext &node = EnsureNodeContext(request.context); | ||||
bool res = FindScriptPubKey( | bool res = FindScriptPubKey( | ||||
g_scan_progress, g_should_abort_scan, count, pcursor.get(), | g_scan_progress, g_should_abort_scan, count, pcursor.get(), | ||||
needles, coins, node.rpc_interruption_point); | needles, coins, node.rpc_interruption_point); | ||||
result.pushKV("success", res); | result.pushKV("success", res); | ||||
result.pushKV("txouts", count); | result.pushKV("txouts", count); | ||||
▲ Show 20 Lines • Show All 74 Lines • ▼ Show 20 Lines | return RPCHelpMan{ | ||||
"Index is not enabled for filtertype " + | "Index is not enabled for filtertype " + | ||||
filtertype_name); | filtertype_name); | ||||
} | } | ||||
const CBlockIndex *block_index; | const CBlockIndex *block_index; | ||||
bool block_was_connected; | bool block_was_connected; | ||||
{ | { | ||||
LOCK(cs_main); | LOCK(cs_main); | ||||
block_index = | block_index = EnsureChainman(request.context) | ||||
g_chainman.m_blockman.LookupBlockIndex(block_hash); | .m_blockman.LookupBlockIndex(block_hash); | ||||
if (!block_index) { | if (!block_index) { | ||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, | ||||
"Block not found"); | "Block not found"); | ||||
} | } | ||||
block_was_connected = | block_was_connected = | ||||
block_index->IsValid(BlockValidity::SCRIPTS); | block_index->IsValid(BlockValidity::SCRIPTS); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 116 Lines • ▼ Show 20 Lines | CBlockIndex *tip; | ||||
if (!GetUTXOStats(&chainstate.CoinsDB(), chainstate.m_blockman, stats, | if (!GetUTXOStats(&chainstate.CoinsDB(), chainstate.m_blockman, stats, | ||||
CoinStatsHashType::NONE, | CoinStatsHashType::NONE, | ||||
node.rpc_interruption_point)) { | node.rpc_interruption_point)) { | ||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set"); | throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to read UTXO set"); | ||||
} | } | ||||
pcursor = | pcursor = | ||||
std::unique_ptr<CCoinsViewCursor>(chainstate.CoinsDB().Cursor()); | std::unique_ptr<CCoinsViewCursor>(chainstate.CoinsDB().Cursor()); | ||||
tip = g_chainman.m_blockman.LookupBlockIndex(stats.hashBlock); | tip = chainstate.m_blockman.LookupBlockIndex(stats.hashBlock); | ||||
CHECK_NONFATAL(tip); | CHECK_NONFATAL(tip); | ||||
} | } | ||||
SnapshotMetadata metadata{tip->GetBlockHash(), stats.coins_count, | SnapshotMetadata metadata{tip->GetBlockHash(), stats.coins_count, | ||||
uint64_t(tip->GetChainTxCount())}; | uint64_t(tip->GetChainTxCount())}; | ||||
afile << metadata; | afile << metadata; | ||||
▲ Show 20 Lines • Show All 73 Lines • Show Last 20 Lines |