Inside Bitcoin
Opening the selected file…
Inside Bitcoin
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) 2011-present The Bitcoin Core developers2// Distributed under the MIT software license, see the accompanying3// file COPYING or http://www.opensource.org/licenses/mit-license.php.5#include <bitcoin-build-config.h> // IWYU pragma: keep7#include <qt/rpcconsole.h>8#include <qt/forms/ui_debugwindow.h>10#include <chainparams.h>11#include <common/system.h>12#include <interfaces/node.h>13#include <node/connection_types.h>14#include <qt/bantablemodel.h>15#include <qt/clientmodel.h>16#include <qt/guiutil.h>17#include <qt/peertablesortproxy.h>18#include <qt/platformstyle.h>19#ifdef ENABLE_WALLET20#include <qt/walletmodel.h>21#endif // ENABLE_WALLET22#include <rpc/client.h>23#include <rpc/server.h>24#include <util/byte_units.h>25#include <util/strencodings.h>26#include <util/string.h>27#include <util/time.h>28#include <util/threadnames.h>30#include <univalue.h>32#include <QAbstractButton>33#include <QAbstractItemModel>34#include <QDateTime>35#include <QFont>36#include <QKeyEvent>37#include <QKeySequence>38#include <QLatin1String>39#include <QLocale>40#include <QMenu>41#include <QMessageBox>42#include <QScreen>43#include <QScrollBar>44#include <QSettings>45#include <QString>46#include <QStringList>47#include <QStyledItemDelegate>48#include <QTime>49#include <QTimer>50#include <QVariant>52#include <chrono>54using util::Join;56const int CONSOLE_HISTORY = 50;57const int INITIAL_TRAFFIC_GRAPH_MINS = 30;58const QSize FONT_RANGE(4, 40);59const char fontSizeSettingsKey[] = "consoleFontSize";61const struct {62const char *url;63const char *source;64} ICON_MAPPING[] = {65{"cmd-request", ":/icons/tx_input"},66{"cmd-reply", ":/icons/tx_output"},67{"cmd-error", ":/icons/tx_output"},68{"misc", ":/icons/tx_inout"},69{nullptr, nullptr}70};72namespace {74// don't add private key handling cmd's to the history75const QStringList historyFilter = QStringList()76<< "createwallet"77<< "createwalletdescriptor"78<< "migratewallet"79<< "signmessagewithprivkey"80<< "signrawtransactionwithkey"81<< "walletpassphrase"82<< "walletpassphrasechange"83<< "encryptwallet";85}87/* Object for executing console RPC commands in a separate thread.88*/89class RPCExecutor : public QObject90{91Q_OBJECT92public:93explicit RPCExecutor(interfaces::Node& node) : m_node(node) {}95public Q_SLOTS:96void request(const QString &command, const QString& wallet_name);98Q_SIGNALS:99void reply(int category, const QString &command);101private:102interfaces::Node& m_node;103};105class PeerIdViewDelegate : public QStyledItemDelegate106{107Q_OBJECT108public:109explicit PeerIdViewDelegate(QObject* parent = nullptr)110: QStyledItemDelegate(parent) {}112QString displayText(const QVariant& value, const QLocale& locale) const override113{114// Additional spaces should visually separate right-aligned content115// from the next column to the right.116return value.toString() + QLatin1String(" ");117}118};120#include <qt/rpcconsole.moc>122/**123* Split shell command line into a list of arguments and optionally execute the command(s).124* Aims to emulate \c bash and friends.125*126* - Command nesting is possible with parenthesis; for example: validateaddress(getnewaddress())127* - Arguments are delimited with whitespace or comma128* - Extra whitespace at the beginning and end and between arguments will be ignored129* - Text can be "double" or 'single' quoted130* - The backslash \c \ is used as escape character131* - Outside quotes, any character can be escaped132* - Within double quotes, only escape \c " and backslashes before a \c " or another backslash133* - Within single quotes, no escaping is possible and no special interpretation takes place134*135* @param[in] node optional node to execute command on136* @param[out] strResult stringified result from the executed command(chain)137* @param[in] strCommand Command line to split138* @param[in] fExecute set true if you want the command to be executed139* @param[out] pstrFilteredOut Command line, filtered to remove any sensitive data140*/142bool RPCConsole::RPCParseCommandLine(interfaces::Node* node, std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut, const QString& wallet_name)143{144std::vector< std::vector<std::string> > stack;145stack.emplace_back();147enum CmdParseState148{149STATE_EATING_SPACES,150STATE_EATING_SPACES_IN_ARG,151STATE_EATING_SPACES_IN_BRACKETS,152STATE_ARGUMENT,153STATE_SINGLEQUOTED,154STATE_DOUBLEQUOTED,155STATE_ESCAPE_OUTER,156STATE_ESCAPE_DOUBLEQUOTED,157STATE_COMMAND_EXECUTED,158STATE_COMMAND_EXECUTED_INNER159} state = STATE_EATING_SPACES;160std::string curarg;161UniValue lastResult;162bool command_parsed = false;163unsigned nDepthInsideSensitive = 0;164size_t filter_begin_pos = 0, chpos;165std::vector<std::pair<size_t, size_t>> filter_ranges;167auto add_to_current_stack = [&](const std::string& strArg) {168if (stack.back().empty() && (!nDepthInsideSensitive) && historyFilter.contains(QString::fromStdString(strArg), Qt::CaseInsensitive)) {169nDepthInsideSensitive = 1;170filter_begin_pos = chpos;171}172// Make sure stack is not empty before adding something173if (stack.empty()) {174stack.emplace_back();175}176stack.back().push_back(strArg);177};179auto close_out_params = [&]() {180if (nDepthInsideSensitive) {181if (!--nDepthInsideSensitive) {182assert(filter_begin_pos);183filter_ranges.emplace_back(filter_begin_pos, chpos);184filter_begin_pos = 0;185}186}187stack.pop_back();188};190std::string strCommandTerminated = strCommand;191if (strCommandTerminated.back() != '\n')192strCommandTerminated += "\n";193for (chpos = 0; chpos < strCommandTerminated.size(); ++chpos)194{195char ch = strCommandTerminated[chpos];196switch(state)197{198case STATE_COMMAND_EXECUTED_INNER:199case STATE_COMMAND_EXECUTED:200{201bool breakParsing = true;202switch(ch)203{204case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER; break;205default:206if (state == STATE_COMMAND_EXECUTED_INNER)207{208if (ch != ']')209{210// append char to the current argument (which is also used for the query command)211curarg += ch;212break;213}214if (curarg.size() && fExecute)215{216// if we have a value query, query arrays with index and objects with a string key217UniValue subelement;218if (lastResult.isArray())219{220const auto parsed{ToIntegral<size_t>(curarg)};221if (!parsed) {222throw std::runtime_error("Invalid result query");223}224subelement = lastResult[parsed.value()];225}226else if (lastResult.isObject())227subelement = lastResult.find_value(curarg);228else229throw std::runtime_error("Invalid result query"); //no array or object: abort230lastResult = subelement;231}233state = STATE_COMMAND_EXECUTED;234break;235}236// don't break parsing when the char is required for the next argument237breakParsing = false;239// pop the stack and return the result to the current command arguments240close_out_params();242// don't stringify the json in case of a string to avoid doublequotes243if (lastResult.isStr())244curarg = lastResult.get_str();245else246curarg = lastResult.write(2);248// if we have a non empty result, use it as stack argument otherwise as general result249if (curarg.size())250{
Independent explanations by MyBitcoinExplorer. Not affiliated with or endorsed by Bitcoin Core. Guides are educational and do not replace the source or its tests.
Bitcoin Core source © its contributors, distributed under the MIT license. Original notices and bundled third-party licenses are retained in the source tree.