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.
1002if (cmd.isEmpty()) {1003return;1004}1006std::string strFilteredCmd;1007try {1008std::string dummy;1009if (!RPCParseCommandLine(nullptr, dummy, cmd.toStdString(), false, &strFilteredCmd)) {1010// Failed to parse command, so we cannot even filter it for the history1011throw std::runtime_error("Invalid command line");1012}1013} catch (const std::exception& e) {1014QMessageBox::critical(this, "Error", QString("Error: ") + QString::fromStdString(e.what()));1015return;1016}1018// A special case allows to request shutdown even a long-running command is executed.1019if (cmd == QLatin1String("stop")) {1020std::string dummy;1021RPCExecuteCommandLine(m_node, dummy, cmd.toStdString());1022return;1023}1025if (m_is_executing) {1026return;1027}1029ui->lineEdit->clear();1031QString in_use_wallet_name;1032#ifdef ENABLE_WALLET1033WalletModel* wallet_model = ui->WalletSelector->currentData().value<WalletModel*>();1034in_use_wallet_name = wallet_model ? wallet_model->getWalletName() : QString();1035if (m_last_wallet_model != wallet_model) {1036if (wallet_model) {1037message(CMD_REQUEST, tr("Executing command using \"%1\" wallet").arg(wallet_model->getWalletName()));1038} else {1039message(CMD_REQUEST, tr("Executing command without any wallet"));1040}1041m_last_wallet_model = wallet_model;1042}1043#endif // ENABLE_WALLET1045message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));1046//: A console message indicating an entered command is currently being executed.1047message(CMD_REPLY, tr("Executing…"));1048m_is_executing = true;1050QMetaObject::invokeMethod(m_executor, [this, cmd, in_use_wallet_name] {1051m_executor->request(cmd, in_use_wallet_name);1052});1054cmd = QString::fromStdString(strFilteredCmd);1056// Remove command, if already in history1057history.removeOne(cmd);1058// Append command to history1059history.append(cmd);1060// Enforce maximum history size1061while (history.size() > CONSOLE_HISTORY) {1062history.removeFirst();1063}1064// Set pointer to end of history1065historyPtr = history.size();1067// Scroll console view to end1068scrollToEnd();1069}1071void RPCConsole::browseHistory(int offset)1072{1073// store current text when start browsing through the history1074if (historyPtr == history.size()) {1075cmdBeforeBrowsing = ui->lineEdit->text();1076}1078historyPtr += offset;1079if(historyPtr < 0)1080historyPtr = 0;1081if(historyPtr > history.size())1082historyPtr = history.size();1083QString cmd;1084if(historyPtr < history.size())1085cmd = history.at(historyPtr);1086else if (!cmdBeforeBrowsing.isNull()) {1087cmd = cmdBeforeBrowsing;1088}1089ui->lineEdit->setText(cmd);1090}1092void RPCConsole::startExecutor()1093{1094m_executor = new RPCExecutor(m_node);1095m_executor->moveToThread(&thread);1097// Replies from executor object must go to this object1098connect(m_executor, &RPCExecutor::reply, this, [this](int category, const QString& command) {1099// Remove "Executing…" message.1100ui->messagesWidget->undo();1101message(category, command);1102scrollToEnd();1103m_is_executing = false;1104});1106// Make sure executor object is deleted in its own thread1107connect(&thread, &QThread::finished, m_executor, &RPCExecutor::deleteLater);1109// Default implementation of QThread::run() simply spins up an event loop in the thread,1110// which is what we want.1111thread.start();1112QTimer::singleShot(0, m_executor, []() {1113util::ThreadRename("qt-rpcconsole");1114});1115}1117void RPCConsole::on_tabWidget_currentChanged(int index)1118{1119if (ui->tabWidget->widget(index) == ui->tab_console) {1120ui->lineEdit->setFocus();1121}1122}1124void RPCConsole::on_openDebugLogfileButton_clicked()1125{1126GUIUtil::openDebugLogfile();1127}1129void RPCConsole::scrollToEnd()1130{1131QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();1132scrollbar->setValue(scrollbar->maximum());1133}1135void RPCConsole::on_sldGraphRange_valueChanged(int value)1136{1137const int multiplier = 5; // each position on the slider represents 5 min1138int mins = value * multiplier;1139setTrafficGraphRange(mins);1140}1142void RPCConsole::setTrafficGraphRange(int mins)1143{1144ui->trafficGraph->setGraphRange(std::chrono::minutes{mins});1145ui->lblGraphRange->setText(GUIUtil::formatDurationStr(std::chrono::minutes{mins}));1146}1148void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)1149{1150ui->lblBytesIn->setText(GUIUtil::formatBytes(totalBytesIn));1151ui->lblBytesOut->setText(GUIUtil::formatBytes(totalBytesOut));1152}1154void RPCConsole::updateDetailWidget()1155{1156const QList<QModelIndex> selected_peers = GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId);1157if (!clientModel || !clientModel->getPeerTableModel() || selected_peers.size() != 1) {1158ui->peersTabRightPanel->hide();1159ui->peerHeading->setText(tr("Select a peer to view detailed information."));1160return;1161}1162const auto stats = selected_peers.first().data(PeerTableModel::StatsRole).value<CNodeCombinedStats*>();1163// update the detail ui with latest node information1164QString peerAddrDetails(QString::fromStdString(stats->nodeStats.m_addr_name) + " ");1165peerAddrDetails += tr("(peer: %1)").arg(QString::number(stats->nodeStats.nodeid));1166if (!stats->nodeStats.addrLocal.empty())1167peerAddrDetails += "<br />" + tr("via %1").arg(QString::fromStdString(stats->nodeStats.addrLocal));1168ui->peerHeading->setText(peerAddrDetails);1169QString bip152_hb_settings;1170if (stats->nodeStats.m_bip152_highbandwidth_to) bip152_hb_settings = ts.to;1171if (stats->nodeStats.m_bip152_highbandwidth_from) bip152_hb_settings += (bip152_hb_settings.isEmpty() ? ts.from : QLatin1Char('/') + ts.from);1172if (bip152_hb_settings.isEmpty()) bip152_hb_settings = ts.no;1173ui->peerHighBandwidth->setText(bip152_hb_settings);1174const auto now{NodeClock::now()};1175const auto time_now{GetTime<std::chrono::seconds>()};1176ui->peerConnTime->setText(GUIUtil::formatDurationStr(now - stats->nodeStats.m_connected));1177ui->peerLastBlock->setText(TimeDurationField(time_now, stats->nodeStats.m_last_block_time));1178ui->peerLastTx->setText(TimeDurationField(time_now, stats->nodeStats.m_last_tx_time));1179ui->peerLastSend->setText(TimeDurationField(now, stats->nodeStats.m_last_send));1180ui->peerLastRecv->setText(TimeDurationField(now, stats->nodeStats.m_last_recv));1181ui->peerBytesSent->setText(GUIUtil::formatBytes(stats->nodeStats.nSendBytes));1182ui->peerBytesRecv->setText(GUIUtil::formatBytes(stats->nodeStats.nRecvBytes));1183ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.m_last_ping_time));1184ui->peerMinPing->setText(GUIUtil::formatPingTime(stats->nodeStats.m_min_ping_time));1185ui->peerVersion->setText(stats->nodeStats.nVersion ? QString::number(stats->nodeStats.nVersion) : ts.na);1186ui->peerSubversion->setText(!stats->nodeStats.cleanSubVer.empty() ? QString::fromStdString(stats->nodeStats.cleanSubVer) : ts.na);1187ui->peerConnectionType->setText(GUIUtil::ConnectionTypeToQString(stats->nodeStats.m_conn_type, /*prepend_direction=*/true));1188ui->peerTransportType->setText(QString::fromStdString(TransportTypeAsString(stats->nodeStats.m_transport_type)));1189if (stats->nodeStats.m_transport_type == TransportProtocolType::V2) {1190ui->peerSessionIdLabel->setVisible(true);1191ui->peerSessionId->setVisible(true);1192ui->peerSessionId->setText(QString::fromStdString(stats->nodeStats.m_session_id));1193} else {1194ui->peerSessionIdLabel->setVisible(false);1195ui->peerSessionId->setVisible(false);1196}1197ui->peerNetwork->setText(GUIUtil::NetworkToQString(stats->nodeStats.m_network));1198if (stats->nodeStats.m_permission_flags == NetPermissionFlags::None) {1199ui->peerPermissions->setText(ts.na);1200} else {1201QStringList permissions;1202for (const auto& permission : NetPermissions::ToStrings(stats->nodeStats.m_permission_flags)) {1203permissions.append(QString::fromStdString(permission));1204}1205ui->peerPermissions->setText(permissions.join(" & "));1206}1207ui->peerMappedAS->setText(stats->nodeStats.m_mapped_as != 0 ? QString::number(stats->nodeStats.m_mapped_as) : ts.na);1209// This check fails for example if the lock was busy and1210// nodeStateStats couldn't be fetched.1211if (stats->fNodeStateStatsAvailable) {1212ui->timeoffset->setText(GUIUtil::formatTimeOffset(Ticks<std::chrono::seconds>(stats->nodeStateStats.time_offset)));1213ui->peerServices->setText(GUIUtil::formatServicesStr(stats->nodeStateStats.their_services));1214// Sync height is init to -11215if (stats->nodeStateStats.nSyncHeight > -1) {1216ui->peerSyncHeight->setText(QString("%1").arg(stats->nodeStateStats.nSyncHeight));1217} else {1218ui->peerSyncHeight->setText(ts.unknown);1219}1220// Common height is init to -11221if (stats->nodeStateStats.nCommonHeight > -1) {1222ui->peerCommonHeight->setText(QString("%1").arg(stats->nodeStateStats.nCommonHeight));1223} else {1224ui->peerCommonHeight->setText(ts.unknown);1225}1226ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStateStats.m_ping_wait));1227ui->peerAddrRelayEnabled->setText(stats->nodeStateStats.m_addr_relay_enabled ? ts.yes : ts.no);1228ui->peerAddrProcessed->setText(QString::number(stats->nodeStateStats.m_addr_processed));1229ui->peerAddrRateLimited->setText(QString::number(stats->nodeStateStats.m_addr_rate_limited));1230ui->peerRelayTxes->setText(stats->nodeStateStats.m_relay_txs ? ts.yes : ts.no);1231}1233ui->hidePeersDetailButton->setIcon(platformStyle->SingleColorIcon(QStringLiteral(":/icons/remove")));1234ui->peersTabRightPanel->show();1235}1237void RPCConsole::resizeEvent(QResizeEvent *event)1238{1239QWidget::resizeEvent(event);1240}1242void RPCConsole::showEvent(QShowEvent *event)1243{1244QWidget::showEvent(event);1246if (!clientModel || !clientModel->getPeerTableModel())1247return;1249// start PeerTableModel auto refresh1250clientModel->getPeerTableModel()->startAutoRefresh();
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.