Inside Bitcoin
Opening the selected file…
Opening the selected file…
The code behind the network, with room to understand it.
Release published 2026-10-28 · Snapshot fetched 2026-11-01. Latest stable release at fetch time; development branches and Git history are excluded. Only the selected code window and visible folders load here.
1// Copyright (c) 2010 Satoshi Nakamoto2// Copyright (c) 2009-present The Bitcoin Core developers3// Distributed under the MIT software license, see the accompanying4// file COPYING or http://www.opensource.org/licenses/mit-license.php.6#include <bitcoin-build-config.h> // IWYU pragma: keep8#include <rpc/register.h> // IWYU pragma: associated10#include <chainparams.h>11#include <index/base.h>12#include <index/blockfilterindex.h>13#include <index/coinstatsindex.h>14#include <index/txindex.h>15#include <index/txospenderindex.h>16#include <interfaces/chain.h>17#include <interfaces/echo.h>18#include <interfaces/init.h>19#include <interfaces/ipc.h>20#include <kernel/cs_main.h>21#include <logging.h>22#include <node/context.h>23#include <rpc/protocol.h>24#include <rpc/request.h>25#include <rpc/server.h>26#include <rpc/server_util.h>27#include <rpc/util.h>28#include <scheduler.h>29#include <support/lockedpool.h>30#include <sync.h>31#include <tinyformat.h>32#include <univalue.h>33#include <util/check.h>34#include <util/time.h>35#include <validationinterface.h>37#include <cstdint>38#include <cstdio>39#include <cstdlib>40#include <limits>41#include <memory>42#include <optional>43#include <stdexcept>44#include <string>45#include <utility>46#include <vector>47#ifdef HAVE_MALLOC_INFO48#include <malloc.h>49#endif50#include <string_view>52using node::NodeContext;54static RPCMethod setmocktime()55{56return RPCMethod{57"setmocktime",58"Set the local time to given timestamp (-regtest only)\n",59{60{"timestamp", RPCArg::Type::NUM, RPCArg::Optional::NO, UNIX_EPOCH_TIME + "\n"61"Pass 0 to go back to using the system time."},62},63RPCResult{RPCResult::Type::NONE, "", ""},64RPCExamples{""},65[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue66{67if (!Params().IsMockableChain()) {68throw std::runtime_error("setmocktime is for regression testing (-regtest mode) only");69}71// For now, don't change mocktime if we're in the middle of validation, as72// this could have an effect on mempool time-based eviction, as well as73// IsCurrentForFeeEstimation() and IsInitialBlockDownload().74// TODO: figure out the right way to synchronize around mocktime, and75// ensure all call sites of GetTime() are accessing this safely.76LOCK(cs_main);78const int64_t time{request.params[0].getInt<int64_t>()};79// block timestamps are uint32_t, so mocking time beyond that is meaningless for anything80// consensus-related and can cause integer overflow/truncation issues in time arithmetic.81constexpr int64_t max_time{std::numeric_limits<uint32_t>::max()};82if (time < 0 || time > max_time) {83throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Mocktime must be in the range [0, %s], not %s.", max_time, time));84}86SetMockTime(std::chrono::seconds{time});87const NodeContext& node_context{EnsureAnyNodeContext(request.context)};88for (const auto& chain_client : node_context.chain_clients) {89chain_client->setMockTime(time);90}92return UniValue::VNULL;93},94};95}97static RPCMethod mockscheduler()98{99return RPCMethod{100"mockscheduler",101"Bump the scheduler into the future (-regtest only)\n",102{103{"delta_time", RPCArg::Type::NUM, RPCArg::Optional::NO, "Number of seconds to forward the scheduler into the future." },104},105RPCResult{RPCResult::Type::NONE, "", ""},106RPCExamples{""},107[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue108{109if (!Params().IsMockableChain()) {110throw std::runtime_error("mockscheduler is for regression testing (-regtest mode) only");111}113int64_t delta_seconds = request.params[0].getInt<int64_t>();114if (delta_seconds <= 0 || delta_seconds > 3600) {115throw std::runtime_error("delta_time must be between 1 and 3600 seconds (1 hr)");116}118const NodeContext& node_context{EnsureAnyNodeContext(request.context)};119CHECK_NONFATAL(node_context.scheduler)->MockForward(std::chrono::seconds{delta_seconds});120CHECK_NONFATAL(node_context.validation_signals)->SyncWithValidationInterfaceQueue();121for (const auto& chain_client : node_context.chain_clients) {122chain_client->schedulerMockForward(std::chrono::seconds(delta_seconds));123}125return UniValue::VNULL;126},127};128}130static UniValue RPCLockedMemoryInfo()131{132LockedPool::Stats stats = LockedPoolManager::Instance().stats();133UniValue obj(UniValue::VOBJ);134obj.pushKV("used", stats.used);135obj.pushKV("free", stats.free);136obj.pushKV("total", stats.total);137obj.pushKV("locked", stats.locked);138obj.pushKV("chunks_used", stats.chunks_used);139obj.pushKV("chunks_free", stats.chunks_free);140return obj;141}143#ifdef HAVE_MALLOC_INFO144static std::string RPCMallocInfo()145{146char *ptr = nullptr;147size_t size = 0;148FILE *f = open_memstream(&ptr, &size);149if (f) {150malloc_info(0, f);151fclose(f);152if (ptr) {153std::string rv(ptr, size);154free(ptr);155return rv;156}157}158return "";159}160#endif162static RPCMethod getmemoryinfo()163{164/* Please, avoid using the word "pool" here in the RPC interface or help,165* as users will undoubtedly confuse it with the other "memory pool"166*/167return RPCMethod{"getmemoryinfo",168"Returns an object containing information about memory usage.\n",169{170{"mode", RPCArg::Type::STR, RPCArg::Default{"stats"}, "determines what kind of information is returned.\n"171" - \"stats\" returns general statistics about memory usage in the daemon.\n"172" - \"mallocinfo\" returns an XML string describing low-level heap state (only available if compiled with glibc)."},173},174{175RPCResult{"mode \"stats\"",176RPCResult::Type::OBJ, "", "",177{178{RPCResult::Type::OBJ, "locked", "Information about locked memory manager",179{180{RPCResult::Type::NUM, "used", "Number of bytes used"},181{RPCResult::Type::NUM, "free", "Number of bytes available in current arenas"},182{RPCResult::Type::NUM, "total", "Total number of bytes managed"},183{RPCResult::Type::NUM, "locked", "Amount of bytes that succeeded locking. If this number is smaller than total, locking pages failed at some point and key data could be swapped to disk."},184{RPCResult::Type::NUM, "chunks_used", "Number allocated chunks"},185{RPCResult::Type::NUM, "chunks_free", "Number unused chunks"},186}},187}188},189RPCResult{"mode \"mallocinfo\"",190RPCResult::Type::STR, "", "\"<malloc version=\"1\">...\""191},192},193RPCExamples{194HelpExampleCli("getmemoryinfo", "")195+ HelpExampleRpc("getmemoryinfo", "")196},197[](const RPCMethod& self, const JSONRPCRequest& request) -> UniValue198{199auto mode{self.Arg<std::string_view>("mode")};200if (mode == "stats") {201UniValue obj(UniValue::VOBJ);202obj.pushKV("locked", RPCLockedMemoryInfo());203return obj;204} else if (mode == "mallocinfo") {205#ifdef HAVE_MALLOC_INFO206return RPCMallocInfo();207#else208throw JSONRPCError(RPC_INVALID_PARAMETER, "mallocinfo mode not available");209#endif210} else {211throw JSONRPCError(RPC_INVALID_PARAMETER, tfm::format("unknown mode %s", mode));212}213},214};215}217static void EnableOrDisableLogCategories(UniValue cats, bool enable) {218cats = cats.get_array();219for (unsigned int i = 0; i < cats.size(); ++i) {220std::string cat = cats[i].get_str();222bool success;223if (enable) {224success = LogInstance().EnableCategory(cat);225} else {226success = LogInstance().DisableCategory(cat);227}229if (!success) {230throw JSONRPCError(RPC_INVALID_PARAMETER, "unknown logging category " + cat);231}232}233}235static RPCMethod logging()236{237return RPCMethod{"logging",238"Gets and sets the logging configuration.\n"239"When called without an argument, returns the list of categories with status that are currently being debug logged or not.\n"240"When called with arguments, adds or removes categories from debug logging and return the lists above.\n"241"The arguments are evaluated in order \"include\", \"exclude\".\n"242"If an item is both included and excluded, it will thus end up being excluded.\n"243"The valid logging categories are: " + LogInstance().LogCategoriesString() + "\n"244"In addition, the following are available as category names with special meanings:\n"245" - \"all\", \"1\" : represent all logging categories.\n"246,247{248{"include", RPCArg::Type::ARR, RPCArg::Optional::OMITTED, "The categories to add to debug logging",249{250{"include_category", RPCArg::Type::STR, RPCArg::Optional::OMITTED, "the valid logging category"},