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.
251if (stack.size())252add_to_current_stack(curarg);253else254strResult = curarg;255}256curarg.clear();257// assume eating space state258state = STATE_EATING_SPACES;259}260if (breakParsing)261break;262[[fallthrough]];263}264case STATE_ARGUMENT: // In or after argument265case STATE_EATING_SPACES_IN_ARG:266case STATE_EATING_SPACES_IN_BRACKETS:267case STATE_EATING_SPACES: // Handle runs of whitespace268switch(ch)269{270case '"': state = STATE_DOUBLEQUOTED; break;271case '\'': state = STATE_SINGLEQUOTED; break;272case '\\': state = STATE_ESCAPE_OUTER; break;273case '(': case ')': case '\n':274if (state == STATE_EATING_SPACES_IN_ARG)275throw std::runtime_error("Invalid Syntax");276if (state == STATE_ARGUMENT)277{278if (ch == '(' && stack.size() && stack.back().size() > 0)279{280if (nDepthInsideSensitive) {281++nDepthInsideSensitive;282}283stack.emplace_back();284}286// don't allow commands after executed commands on baselevel287if (!stack.size())288throw std::runtime_error("Invalid Syntax");290add_to_current_stack(curarg);291curarg.clear();292state = STATE_EATING_SPACES_IN_BRACKETS;293}294if ((ch == ')' || ch == '\n') && stack.size() > 0 && stack.back().size() > 0)295{296if (fExecute) {297// Convert argument list to JSON objects in method-dependent way,298// and pass it along with the method name to the dispatcher.299UniValue params = RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()));300std::string method = stack.back()[0];301std::string uri;302if (!wallet_name.isEmpty()) {303QByteArray encodedName = QUrl::toPercentEncoding(wallet_name);304uri = "/wallet/"+std::string(encodedName.constData(), encodedName.length());305}306assert(node);307lastResult = node->executeRpc(method, params, uri);308}310command_parsed = true;311state = STATE_COMMAND_EXECUTED;312curarg.clear();313}314break;315case ' ': case ',': case '\t':316if(state == STATE_EATING_SPACES_IN_ARG && curarg.empty() && ch == ',')317throw std::runtime_error("Invalid Syntax");319else if(state == STATE_ARGUMENT) // Space ends argument320{321add_to_current_stack(curarg);322curarg.clear();323}324if ((state == STATE_EATING_SPACES_IN_BRACKETS || state == STATE_ARGUMENT) && ch == ',')325{326state = STATE_EATING_SPACES_IN_ARG;327break;328}329state = STATE_EATING_SPACES;330break;331default: curarg += ch; state = STATE_ARGUMENT;332}333break;334case STATE_SINGLEQUOTED: // Single-quoted string335switch(ch)336{337case '\'': state = STATE_ARGUMENT; break;338default: curarg += ch;339}340break;341case STATE_DOUBLEQUOTED: // Double-quoted string342switch(ch)343{344case '"': state = STATE_ARGUMENT; break;345case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;346default: curarg += ch;347}348break;349case STATE_ESCAPE_OUTER: // '\' outside quotes350curarg += ch; state = STATE_ARGUMENT;351break;352case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text353if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself354curarg += ch; state = STATE_DOUBLEQUOTED;355break;356}357}358if (pstrFilteredOut) {359if (STATE_COMMAND_EXECUTED == state) {360assert(!stack.empty());361close_out_params();362}363*pstrFilteredOut = strCommand;364for (auto i = filter_ranges.rbegin(); i != filter_ranges.rend(); ++i) {365pstrFilteredOut->replace(i->first, i->second - i->first, "(…)");366}367}368switch(state) // final state369{370case STATE_COMMAND_EXECUTED:371if (lastResult.isStr())372strResult = lastResult.get_str();373else374strResult = lastResult.write(2);375[[fallthrough]];376case STATE_ARGUMENT:377return true;378case STATE_EATING_SPACES:379// Reaching this state without ever parsing a command means the line380// held no command name (e.g. ")", "()", "(", ","); treat it as invalid.381return command_parsed;382default: // ERROR to end in one of the other states383return false;384}385}387void RPCExecutor::request(const QString &command, const QString& wallet_name)388{389try390{391std::string result;392std::string executableCommand = command.toStdString() + "\n";394// Catch the console-only-help command before RPC call is executed and reply with help text as-if a RPC reply.395if(executableCommand == "help-console\n") {396Q_EMIT reply(RPCConsole::CMD_REPLY, QString(("\n"397"This console accepts RPC commands using the standard syntax.\n"398" example: getblockhash 0\n\n"400"This console can also accept RPC commands using the parenthesized syntax.\n"401" example: getblockhash(0)\n\n"403"Commands may be nested when specified with the parenthesized syntax.\n"404" example: getblock(getblockhash(0) 1)\n\n"406"A space or a comma can be used to delimit arguments for either syntax.\n"407" example: getblockhash 0\n"408" getblockhash,0\n\n"410"Named results can be queried with a non-quoted key string in brackets using the parenthesized syntax.\n"411" example: getblock(getblockhash(0) 1)[tx]\n\n"413"Results without keys can be queried with an integer in brackets using the parenthesized syntax.\n"414" example: getblock(getblockhash(0),1)[tx][0]\n\n")));415return;416}417if (!RPCConsole::RPCExecuteCommandLine(m_node, result, executableCommand, nullptr, wallet_name)) {418Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));419return;420}422Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(result));423}424catch (UniValue& objError)425{426try // Nice formatting for standard-format error427{428int code = objError.find_value("code").getInt<int>();429std::string message = objError.find_value("message").get_str();430Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");431}432catch (const std::runtime_error&) // raised when converting to invalid type, i.e. missing code or message433{ // Show raw JSON object434Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(objError.write()));435}436}437catch (const std::exception& e)438{439Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));440}441}443RPCConsole::RPCConsole(interfaces::Node& node, const PlatformStyle *_platformStyle, QWidget *parent) :444QWidget(parent),445m_node(node),446ui(new Ui::RPCConsole),447platformStyle(_platformStyle)448{449ui->setupUi(this);450QSettings settings;451#ifdef ENABLE_WALLET452if (WalletModel::isWalletEnabled()) {453// RPCConsole widget is a window.454if (!restoreGeometry(settings.value("RPCConsoleWindowGeometry").toByteArray())) {455// Restore failed (perhaps missing setting), center the window456move(QGuiApplication::primaryScreen()->availableGeometry().center() - frameGeometry().center());457}458ui->splitter->restoreState(settings.value("RPCConsoleWindowPeersTabSplitterSizes").toByteArray());459} else460#endif // ENABLE_WALLET461{462// RPCConsole is a child widget.463ui->splitter->restoreState(settings.value("RPCConsoleWidgetPeersTabSplitterSizes").toByteArray());464}466m_peer_widget_header_state = settings.value("PeersTabPeerHeaderState").toByteArray();467m_banlist_widget_header_state = settings.value("PeersTabBanlistHeaderState").toByteArray();469constexpr QChar nonbreaking_hyphen(8209);470const std::vector<QString> CONNECTION_TYPE_DOC{471//: Explanatory text for an inbound peer connection.472tr("Inbound: initiated by peer"),473/*: Explanatory text for an outbound peer connection that474relays all network information. This is the default behavior for475outbound connections. */476tr("Outbound Full Relay: default"),477/*: Explanatory text for an outbound peer connection that relays478network information about blocks and not transactions or addresses. */479tr("Outbound Block Relay: does not relay transactions or addresses"),480/*: Explanatory text for an outbound peer connection that was481established manually through one of several methods. The numbered482arguments are stand-ins for the methods available to establish483manual connections. */484tr("Outbound Manual: added using RPC %1 or %2/%3 configuration options")485.arg("addnode")486.arg(QString(nonbreaking_hyphen) + "addnode")487.arg(QString(nonbreaking_hyphen) + "connect"),488/*: Explanatory text for a short-lived outbound peer connection that489is used to test the aliveness of known addresses. */490tr("Outbound Feeler: short-lived, for testing addresses"),491/*: Explanatory text for a short-lived outbound peer connection that is used492to request addresses from a peer. */493tr("Outbound Address Fetch: short-lived, for soliciting addresses"),494/*: Explanatory text for a short-lived outbound peer connection that is used495to broadcast privacy-sensitive data (like our transactions). */496tr("Private broadcast: short-lived, for broadcasting privacy-sensitive transactions")};497const QString connection_types_list{"<ul><li>" + Join(CONNECTION_TYPE_DOC, QString("</li><li>")) + "</li></ul>"};498ui->peerConnectionTypeLabel->setToolTip(ui->peerConnectionTypeLabel->toolTip().arg(connection_types_list));499const std::vector<QString> TRANSPORT_TYPE_DOC{500//: Explanatory text for "detecting" transport type.
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.