5#include <bitcoin-build-config.h>
8#include <qt/forms/ui_debugwindow.h>
10#include <chainparams.h>
31#include <QAbstractButton>
32#include <QAbstractItemModel>
36#include <QKeySequence>
37#include <QLatin1String>
46#include <QStyledItemDelegate>
64 {
"cmd-request",
":/icons/tx_input"},
65 {
"cmd-reply",
":/icons/tx_output"},
66 {
"cmd-error",
":/icons/tx_output"},
67 {
"misc",
":/icons/tx_inout"},
74const QStringList historyFilter = QStringList()
75 <<
"signmessagewithprivkey"
76 <<
"signrawtransactionwithkey"
78 <<
"walletpassphrasechange"
111 timer.setSingleShot(
true);
112 connect(&
timer, &QTimer::timeout, [
this]{
func(); });
125 const char *
Name()
override {
return "Qt"; }
137 : QStyledItemDelegate(parent) {}
139 QString
displayText(
const QVariant& value,
const QLocale& locale)
const override
143 return value.toString() + QLatin1String(
" ");
147#include <qt/rpcconsole.moc>
171 std::vector< std::vector<std::string> > stack;
172 stack.emplace_back();
177 STATE_EATING_SPACES_IN_ARG,
178 STATE_EATING_SPACES_IN_BRACKETS,
183 STATE_ESCAPE_DOUBLEQUOTED,
184 STATE_COMMAND_EXECUTED,
185 STATE_COMMAND_EXECUTED_INNER
186 } state = STATE_EATING_SPACES;
189 unsigned nDepthInsideSensitive = 0;
190 size_t filter_begin_pos = 0, chpos;
191 std::vector<std::pair<size_t, size_t>> filter_ranges;
193 auto add_to_current_stack = [&](
const std::string& strArg) {
194 if (stack.back().empty() && (!nDepthInsideSensitive) && historyFilter.contains(QString::fromStdString(strArg), Qt::CaseInsensitive)) {
195 nDepthInsideSensitive = 1;
196 filter_begin_pos = chpos;
200 stack.emplace_back();
205 auto close_out_params = [&]() {
206 if (nDepthInsideSensitive) {
207 if (!--nDepthInsideSensitive) {
209 filter_ranges.emplace_back(filter_begin_pos, chpos);
210 filter_begin_pos = 0;
216 std::string strCommandTerminated = strCommand;
217 if (strCommandTerminated.back() !=
'\n')
218 strCommandTerminated +=
"\n";
219 for (chpos = 0; chpos < strCommandTerminated.size(); ++chpos)
221 char ch = strCommandTerminated[chpos];
224 case STATE_COMMAND_EXECUTED_INNER:
225 case STATE_COMMAND_EXECUTED:
227 bool breakParsing =
true;
230 case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER;
break;
232 if (state == STATE_COMMAND_EXECUTED_INNER)
240 if (curarg.size() && fExecute)
246 const auto parsed{ToIntegral<size_t>(curarg)};
248 throw std::runtime_error(
"Invalid result query");
250 subelement = lastResult[parsed.value()];
255 throw std::runtime_error(
"Invalid result query");
256 lastResult = subelement;
259 state = STATE_COMMAND_EXECUTED;
263 breakParsing =
false;
269 if (lastResult.
isStr())
272 curarg = lastResult.
write(2);
278 add_to_current_stack(curarg);
284 state = STATE_EATING_SPACES;
291 case STATE_EATING_SPACES_IN_ARG:
292 case STATE_EATING_SPACES_IN_BRACKETS:
293 case STATE_EATING_SPACES:
296 case '"': state = STATE_DOUBLEQUOTED;
break;
297 case '\'': state = STATE_SINGLEQUOTED;
break;
298 case '\\': state = STATE_ESCAPE_OUTER;
break;
299 case '(':
case ')':
case '\n':
300 if (state == STATE_EATING_SPACES_IN_ARG)
301 throw std::runtime_error(
"Invalid Syntax");
302 if (state == STATE_ARGUMENT)
304 if (ch ==
'(' && stack.size() && stack.back().size() > 0)
306 if (nDepthInsideSensitive) {
307 ++nDepthInsideSensitive;
309 stack.emplace_back();
314 throw std::runtime_error(
"Invalid Syntax");
316 add_to_current_stack(curarg);
318 state = STATE_EATING_SPACES_IN_BRACKETS;
320 if ((ch ==
')' || ch ==
'\n') && stack.size() > 0)
325 UniValue params =
RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()));
326 std::string method = stack.back()[0];
330 QByteArray encodedName = QUrl::toPercentEncoding(wallet_model->
getWalletName());
331 uri =
"/wallet/"+std::string(encodedName.constData(), encodedName.length());
335 lastResult =
node->executeRpc(method, params, uri);
338 state = STATE_COMMAND_EXECUTED;
342 case ' ':
case ',':
case '\t':
343 if(state == STATE_EATING_SPACES_IN_ARG && curarg.empty() && ch ==
',')
344 throw std::runtime_error(
"Invalid Syntax");
346 else if(state == STATE_ARGUMENT)
348 add_to_current_stack(curarg);
351 if ((state == STATE_EATING_SPACES_IN_BRACKETS || state == STATE_ARGUMENT) && ch ==
',')
353 state = STATE_EATING_SPACES_IN_ARG;
356 state = STATE_EATING_SPACES;
358 default: curarg += ch; state = STATE_ARGUMENT;
361 case STATE_SINGLEQUOTED:
364 case '\'': state = STATE_ARGUMENT;
break;
365 default: curarg += ch;
368 case STATE_DOUBLEQUOTED:
371 case '"': state = STATE_ARGUMENT;
break;
372 case '\\': state = STATE_ESCAPE_DOUBLEQUOTED;
break;
373 default: curarg += ch;
376 case STATE_ESCAPE_OUTER:
377 curarg += ch; state = STATE_ARGUMENT;
379 case STATE_ESCAPE_DOUBLEQUOTED:
380 if(ch !=
'"' && ch !=
'\\') curarg +=
'\\';
381 curarg += ch; state = STATE_DOUBLEQUOTED;
385 if (pstrFilteredOut) {
386 if (STATE_COMMAND_EXECUTED == state) {
390 *pstrFilteredOut = strCommand;
391 for (
auto i = filter_ranges.rbegin(); i != filter_ranges.rend(); ++i) {
392 pstrFilteredOut->replace(i->first, i->second - i->first,
"(…)");
397 case STATE_COMMAND_EXECUTED:
398 if (lastResult.
isStr())
399 strResult = lastResult.
get_str();
401 strResult = lastResult.
write(2);
404 case STATE_EATING_SPACES:
416 std::string executableCommand =
command.toStdString() +
"\n";
419 if(executableCommand ==
"help-console\n") {
421 "This console accepts RPC commands using the standard syntax.\n"
422 " example: getblockhash 0\n\n"
424 "This console can also accept RPC commands using the parenthesized syntax.\n"
425 " example: getblockhash(0)\n\n"
427 "Commands may be nested when specified with the parenthesized syntax.\n"
428 " example: getblock(getblockhash(0) 1)\n\n"
430 "A space or a comma can be used to delimit arguments for either syntax.\n"
431 " example: getblockhash 0\n"
432 " getblockhash,0\n\n"
434 "Named results can be queried with a non-quoted key string in brackets using the parenthesized syntax.\n"
435 " example: getblock(getblockhash(0) 1)[tx]\n\n"
437 "Results without keys can be queried with an integer in brackets using the parenthesized syntax.\n"
438 " example: getblock(getblockhash(0),1)[tx][0]\n\n")));
456 catch (
const std::runtime_error&)
461 catch (
const std::exception& e)
471 platformStyle(_platformStyle)
478 if (!restoreGeometry(settings.value(
"RPCConsoleWindowGeometry").toByteArray())) {
480 move(QGuiApplication::primaryScreen()->availableGeometry().center() - frameGeometry().center());
482 ui->splitter->restoreState(settings.value(
"RPCConsoleWindowPeersTabSplitterSizes").toByteArray());
487 ui->splitter->restoreState(settings.value(
"RPCConsoleWidgetPeersTabSplitterSizes").toByteArray());
493 constexpr QChar nonbreaking_hyphen(8209);
496 tr(
"Inbound: initiated by peer"),
500 tr(
"Outbound Full Relay: default"),
503 tr(
"Outbound Block Relay: does not relay transactions or addresses"),
508 tr(
"Outbound Manual: added using RPC %1 or %2/%3 configuration options")
510 .arg(QString(nonbreaking_hyphen) +
"addnode")
511 .arg(QString(nonbreaking_hyphen) +
"connect"),
514 tr(
"Outbound Feeler: short-lived, for testing addresses"),
517 tr(
"Outbound Address Fetch: short-lived, for soliciting addresses")};
518 const QString connection_types_list{
"<ul><li>" +
Join(
CONNECTION_TYPE_DOC, QString(
"</li><li>")) +
"</li></ul>"};
519 ui->peerConnectionTypeLabel->setToolTip(
ui->peerConnectionTypeLabel->toolTip().arg(connection_types_list));
522 tr(
"detecting: peer could be v1 or v2"),
524 tr(
"v1: unencrypted, plaintext transport protocol"),
526 tr(
"v2: BIP324 encrypted transport protocol")};
527 const QString transport_types_list{
"<ul><li>" +
Join(
TRANSPORT_TYPE_DOC, QString(
"</li><li>")) +
"</li></ul>"};
528 ui->peerTransportTypeLabel->setToolTip(
ui->peerTransportTypeLabel->toolTip().arg(transport_types_list));
529 const QString hb_list{
"<ul><li>\""
530 +
ts.
to +
"\" – " + tr(
"we selected the peer for high bandwidth relay") +
"</li><li>\""
531 +
ts.
from +
"\" – " + tr(
"the peer selected us for high bandwidth relay") +
"</li><li>\""
532 +
ts.
no +
"\" – " + tr(
"no high bandwidth relay selected") +
"</li></ul>"};
533 ui->peerHighBandwidthLabel->setToolTip(
ui->peerHighBandwidthLabel->toolTip().arg(hb_list));
534 ui->dataDir->setToolTip(
ui->dataDir->toolTip().arg(QString(nonbreaking_hyphen) +
"datadir"));
535 ui->blocksDir->setToolTip(
ui->blocksDir->toolTip().arg(QString(nonbreaking_hyphen) +
"blocksdir"));
536 ui->openDebugLogfileButton->setToolTip(
ui->openDebugLogfileButton->toolTip().arg(CLIENT_NAME));
545 ui->fontBiggerButton->setShortcut(tr(
"Ctrl++"));
551 ui->fontSmallerButton->setShortcut(tr(
"Ctrl+-"));
558 ui->lineEdit->installEventFilter(
this);
559 ui->lineEdit->setMaxLength(16 * 1024 * 1024);
560 ui->messagesWidget->installEventFilter(
this);
563 connect(
ui->clearButton, &QAbstractButton::clicked, [
this] { clear(); });
569 ui->WalletSelector->setVisible(
false);
570 ui->WalletSelectorLabel->setVisible(
false);
595 settings.setValue(
"RPCConsoleWindowGeometry", saveGeometry());
596 settings.setValue(
"RPCConsoleWindowPeersTabSplitterSizes",
ui->splitter->saveState());
601 settings.setValue(
"RPCConsoleWidgetPeersTabSplitterSizes",
ui->splitter->saveState());
614 if(event->type() == QEvent::KeyPress)
616 QKeyEvent *keyevt =
static_cast<QKeyEvent*
>(event);
617 int key = keyevt->key();
618 Qt::KeyboardModifiers mod = keyevt->modifiers();
621 case Qt::Key_Up:
if(obj ==
ui->lineEdit) {
browseHistory(-1);
return true; }
break;
622 case Qt::Key_Down:
if(obj ==
ui->lineEdit) {
browseHistory(1);
return true; }
break;
624 case Qt::Key_PageDown:
625 if (obj ==
ui->lineEdit) {
626 QApplication::sendEvent(
ui->messagesWidget, keyevt);
634 QApplication::sendEvent(
ui->lineEdit, keyevt);
642 if(obj ==
ui->messagesWidget && (
643 (!mod && !keyevt->text().isEmpty() && key != Qt::Key_Tab) ||
644 ((mod & Qt::ControlModifier) && key == Qt::Key_V) ||
645 ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert)))
647 ui->lineEdit->setFocus();
648 QApplication::sendEvent(
ui->lineEdit, keyevt);
653 return QWidget::eventFilter(obj, event);
660 bool wallet_enabled{
false};
664 if (model && !wallet_enabled) {
670 ui->trafficGraph->setClientModel(model);
690 ui->peerWidget->verticalHeader()->hide();
691 ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
692 ui->peerWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
693 ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu);
700 ui->peerWidget->horizontalHeader()->setSectionResizeMode(
PeerTableModel::Age, QHeaderView::ResizeToContents);
701 ui->peerWidget->horizontalHeader()->setStretchLastSection(
true);
720 connect(model->
getPeerTableModel(), &QAbstractItemModel::dataChanged, [
this] { updateDetailWidget(); });
724 ui->banlistWidget->verticalHeader()->hide();
725 ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
726 ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection);
727 ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu);
734 ui->banlistWidget->horizontalHeader()->setStretchLastSection(
true);
760 ui->networkName->setText(QString::fromStdString(
Params().GetChainTypeString()));
763 QStringList wordList;
765 for (
size_t i = 0; i < commandList.size(); ++i)
767 wordList << commandList[i].c_str();
768 wordList << (
"help " + commandList[i]).c_str();
771 wordList <<
"help-console";
774 autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel);
777 ui->lineEdit->setEnabled(
true);
791void RPCConsole::addWallet(
WalletModel *
const walletModel)
794 ui->WalletSelector->addItem(walletModel->
getDisplayName(), QVariant::fromValue(walletModel));
795 if (
ui->WalletSelector->count() == 2) {
797 ui->WalletSelector->setCurrentIndex(1);
799 if (
ui->WalletSelector->count() > 2) {
800 ui->WalletSelector->setVisible(
true);
801 ui->WalletSelectorLabel->setVisible(
true);
805void RPCConsole::removeWallet(
WalletModel *
const walletModel)
807 ui->WalletSelector->removeItem(
ui->WalletSelector->findData(QVariant::fromValue(walletModel)));
808 if (
ui->WalletSelector->count() == 2) {
809 ui->WalletSelector->setVisible(
false);
810 ui->WalletSelectorLabel->setVisible(
false);
814void RPCConsole::setCurrentWallet(
WalletModel*
const wallet_model)
816 QVariant
data = QVariant::fromValue(wallet_model);
817 ui->WalletSelector->setCurrentIndex(
ui->WalletSelector->findData(
data));
828 default:
return "misc";
851 QString str =
ui->messagesWidget->toHtml();
854 str.replace(QString(
"font-size:%1pt").arg(
consoleFontSize), QString(
"font-size:%1pt").arg(newSize));
861 float oldPosFactor = 1.0 /
ui->messagesWidget->verticalScrollBar()->maximum() *
ui->messagesWidget->verticalScrollBar()->value();
863 ui->messagesWidget->setHtml(str);
864 ui->messagesWidget->verticalScrollBar()->setValue(oldPosFactor *
ui->messagesWidget->verticalScrollBar()->maximum());
869 ui->messagesWidget->clear();
870 if (!keep_prompt)
ui->lineEdit->clear();
871 ui->lineEdit->setFocus();
877 ui->messagesWidget->document()->addResource(
878 QTextDocument::ImageResource,
889 ui->messagesWidget->document()->setDefaultStyleSheet(
892 "td.time { color: #808080; font-size: %2; padding-top: 3px; } "
893 "td.message { font-family: %1; font-size: %2; white-space:pre-wrap; } "
894 "td.cmd-request { color: #006060; } "
895 "td.cmd-error { color: red; } "
896 ".secwarning { color: red; }"
897 "b { color: #006060; } "
901 static const QString welcome_message =
905 tr(
"Welcome to the %1 RPC console.\n"
906 "Use up and down arrows to navigate history, and %2 to clear screen.\n"
907 "Use %3 and %4 to increase or decrease the font size.\n"
908 "Type %5 for an overview of available commands.\n"
909 "For more information on using this console, type %6.\n"
911 "%7WARNING: Scammers have been active, telling users to type"
912 " commands here, stealing their wallet contents. Do not use this console"
913 " without fully understanding the ramifications of a command.%8")
915 "<b>" +
ui->clearButton->shortcut().toString(QKeySequence::NativeText) +
"</b>",
916 "<b>" +
ui->fontBiggerButton->shortcut().toString(QKeySequence::NativeText) +
"</b>",
917 "<b>" +
ui->fontSmallerButton->shortcut().toString(QKeySequence::NativeText) +
"</b>",
919 "<b>help-console</b>",
920 "<span class=\"secwarning\">",
935 if (e->type() == QEvent::PaletteChange) {
942 ui->messagesWidget->document()->addResource(
943 QTextDocument::ImageResource,
949 QWidget::changeEvent(e);
954 QTime time = QTime::currentTime();
955 QString timeString = time.toString();
957 out +=
"<table><tr><td class=\"time\" width=\"65\">" + timeString +
"</td>";
958 out +=
"<td class=\"icon\" width=\"32\"><img src=\"" +
categoryClass(category) +
"\"></td>";
959 out +=
"<td class=\"message " +
categoryClass(category) +
"\" valign=\"middle\">";
964 out +=
"</td></tr></table>";
965 ui->messagesWidget->append(
out);
976 connections +=
" (" + tr(
"Network activity disabled") +
")";
979 ui->numberOfConnections->setText(connections);
981 QString local_addresses;
983 for (
const auto& [addr, info] : hosts) {
984 local_addresses += QString::fromStdString(addr.ToStringAddr());
985 if (!addr.IsI2P()) local_addresses +=
":" + QString::number(info.nPort);
986 local_addresses +=
", ";
988 local_addresses.chop(2);
989 if (local_addresses.isEmpty()) local_addresses = tr(
"None");
991 ui->localAddresses->setText(local_addresses);
1010 ui->numberOfBlocks->setText(QString::number(
count));
1011 ui->lastBlockTime->setText(blockDate.toString());
1017 ui->mempoolNumberTxs->setText(QString::number(numberOfTxs));
1019 const auto cur_usage_str = dynUsage < 1000000 ?
1020 QObject::tr(
"%1 kB").arg(dynUsage / 1000.0, 0,
'f', 2) :
1021 QObject::tr(
"%1 MB").arg(dynUsage / 1000000.0, 0,
'f', 2);
1022 const auto max_usage_str = QObject::tr(
"%1 MB").arg(maxUsage / 1000000.0, 0,
'f', 2);
1024 ui->mempoolSize->setText(cur_usage_str +
" / " + max_usage_str);
1029 QString
cmd =
ui->lineEdit->text().trimmed();
1031 if (
cmd.isEmpty()) {
1035 std::string strFilteredCmd;
1040 throw std::runtime_error(
"Invalid command line");
1042 }
catch (
const std::exception& e) {
1043 QMessageBox::critical(
this,
"Error", QString(
"Error: ") + QString::fromStdString(e.what()));
1048 if (
cmd == QLatin1String(
"stop")) {
1058 ui->lineEdit->clear();
1062 wallet_model =
ui->WalletSelector->currentData().value<
WalletModel*>();
1079 QMetaObject::invokeMethod(
m_executor, [
this,
cmd, wallet_model] {
1083 cmd = QString::fromStdString(strFilteredCmd);
1118 ui->lineEdit->setText(
cmd);
1129 ui->messagesWidget->undo();
1136 connect(&
thread, &QThread::finished,
m_executor, &RPCExecutor::deleteLater);
1148 if (
ui->tabWidget->widget(index) ==
ui->tab_console) {
1149 ui->lineEdit->setFocus();
1160 QScrollBar *scrollbar =
ui->messagesWidget->verticalScrollBar();
1161 scrollbar->setValue(scrollbar->maximum());
1166 const int multiplier = 5;
1167 int mins = value * multiplier;
1173 ui->trafficGraph->setGraphRange(std::chrono::minutes{mins});
1187 ui->peersTabRightPanel->hide();
1188 ui->peerHeading->setText(tr(
"Select a peer to view detailed information."));
1193 QString peerAddrDetails(QString::fromStdString(stats->nodeStats.m_addr_name) +
" ");
1194 peerAddrDetails += tr(
"(peer: %1)").arg(QString::number(stats->nodeStats.nodeid));
1195 if (!stats->nodeStats.addrLocal.empty())
1196 peerAddrDetails +=
"<br />" + tr(
"via %1").arg(QString::fromStdString(stats->nodeStats.addrLocal));
1197 ui->peerHeading->setText(peerAddrDetails);
1198 QString bip152_hb_settings;
1199 if (stats->nodeStats.m_bip152_highbandwidth_to) bip152_hb_settings =
ts.
to;
1200 if (stats->nodeStats.m_bip152_highbandwidth_from) bip152_hb_settings += (bip152_hb_settings.isEmpty() ?
ts.
from : QLatin1Char(
'/') +
ts.
from);
1201 if (bip152_hb_settings.isEmpty()) bip152_hb_settings =
ts.
no;
1202 ui->peerHighBandwidth->setText(bip152_hb_settings);
1203 const auto time_now{GetTime<std::chrono::seconds>()};
1205 ui->peerLastBlock->setText(
TimeDurationField(time_now, stats->nodeStats.m_last_block_time));
1213 if (stats->nodeStats.nVersion) {
1214 ui->peerVersion->setText(QString::number(stats->nodeStats.nVersion));
1216 if (!stats->nodeStats.cleanSubVer.empty()) {
1217 ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer));
1220 ui->peerTransportType->setText(QString::fromStdString(
TransportTypeAsString(stats->nodeStats.m_transport_type)));
1222 ui->peerSessionIdLabel->setVisible(
true);
1223 ui->peerSessionId->setVisible(
true);
1224 ui->peerSessionId->setText(QString::fromStdString(stats->nodeStats.m_session_id));
1226 ui->peerSessionIdLabel->setVisible(
false);
1227 ui->peerSessionId->setVisible(
false);
1231 ui->peerPermissions->setText(
ts.
na);
1233 QStringList permissions;
1235 permissions.append(QString::fromStdString(permission));
1237 ui->peerPermissions->setText(permissions.join(
" & "));
1239 ui->peerMappedAS->setText(stats->nodeStats.m_mapped_as != 0 ? QString::number(stats->nodeStats.m_mapped_as) :
ts.
na);
1243 if (stats->fNodeStateStatsAvailable) {
1247 if (stats->nodeStateStats.nSyncHeight > -1) {
1248 ui->peerSyncHeight->setText(QString(
"%1").arg(stats->nodeStateStats.nSyncHeight));
1253 if (stats->nodeStateStats.nCommonHeight > -1) {
1254 ui->peerCommonHeight->setText(QString(
"%1").arg(stats->nodeStateStats.nCommonHeight));
1258 ui->peerHeight->setText(QString::number(stats->nodeStateStats.m_starting_height));
1260 ui->peerAddrRelayEnabled->setText(stats->nodeStateStats.m_addr_relay_enabled ?
ts.
yes :
ts.
no);
1261 ui->peerAddrProcessed->setText(QString::number(stats->nodeStateStats.m_addr_processed));
1262 ui->peerAddrRateLimited->setText(QString::number(stats->nodeStateStats.m_addr_rate_limited));
1263 ui->peerRelayTxes->setText(stats->nodeStateStats.m_relay_txs ?
ts.
yes :
ts.
no);
1267 ui->peersTabRightPanel->show();
1272 QWidget::resizeEvent(event);
1277 QWidget::showEvent(event);
1293 QWidget::hideEvent(event);
1304 QModelIndex index =
ui->peerWidget->indexAt(point);
1305 if (index.isValid())
1311 QModelIndex index =
ui->banlistWidget->indexAt(point);
1312 if (index.isValid())
1320 for(
int i = 0; i < nodes.count(); i++)
1323 NodeId id = nodes.at(i).data().toLongLong();
1339 m_node.
ban(stats->nodeStats.addr, bantime);
1355 bool unbanned{
false};
1356 for (
const auto& node_index : nodes) {
1357 unbanned |= ban_table_model->
unban(node_index);
1360 ban_table_model->refresh();
1366 ui->peerWidget->selectionModel()->clearSelection();
1377 ui->banlistWidget->setVisible(visible);
1378 ui->banHeading->setVisible(visible);
1383 ui->tabWidget->setCurrentIndex(
int(tabType));
1388 return ui->tabWidget->tabText(
int(tab_type));
1405 this->
ui->label_alerts->setVisible(!warnings.isEmpty());
1406 this->
ui->label_alerts->setText(warnings);
1414 const QString chainType = QString::fromStdString(
Params().GetChainTypeString());
1415 const QString title = tr(
"Node window - [%1]").arg(chainType);
1416 this->setWindowTitle(title);
const CChainParams & Params()
Return the currently selected parameters.
Qt model providing information about banned peers, similar to the "getpeerinfo" RPC call.
bool unban(const QModelIndex &index)
ChainType GetChainType() const
Return the chain type.
Model for Bitcoin network client.
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut)
QString blocksDir() const
QString getStatusBarWarnings() const
Return warnings to be displayed in status bar.
std::map< CNetAddr, LocalServiceInfo > getNetLocalAddresses() const
PeerTableModel * getPeerTableModel()
PeerTableSortProxy * peerTableSortProxy()
void numConnectionsChanged(int count)
QString formatClientStartupTime() const
int getNumConnections(unsigned int flags=CONNECTIONS_ALL) const
Return number of connections, default is in- and outbound (total)
BanTableModel * getBanTableModel()
void numBlocksChanged(int count, const QDateTime &blockDate, double nVerificationProgress, SyncType header, SynchronizationState sync_state)
void alertsChanged(const QString &warnings)
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes, size_t mempoolMaxSizeInBytes)
QString formatFullVersion() const
QString formatSubVersion() const
void networkActiveChanged(bool networkActive)
interfaces::Node & node() const
static std::vector< std::string > ToStrings(NetPermissionFlags flags)
QString displayText(const QVariant &value, const QLocale &locale) const override
PeerIdViewDelegate(QObject *parent=nullptr)
Class for handling RPC timers (used for e.g.
std::function< void()> func
QtRPCTimerBase(std::function< void()> &_func, int64_t millis)
~QtRPCTimerBase()=default
const char * Name() override
Implementation name.
RPCTimerBase * NewTimer(std::function< void()> &func, int64_t millis) override
Factory function for timers.
~QtRPCTimerInterface()=default
Local Bitcoin RPC console.
QMenu * peersTableContextMenu
RPCConsole(interfaces::Node &node, const PlatformStyle *platformStyle, QWidget *parent)
struct RPCConsole::TranslatedStrings ts
void browseHistory(int offset)
Go forward or back in history.
QByteArray m_banlist_widget_header_state
RPCTimerInterface * rpcTimerInterface
QString TimeDurationField(std::chrono::seconds time_now, std::chrono::seconds time_at_event) const
Helper for the output of a time duration field.
void on_lineEdit_returnPressed()
void message(int category, const QString &msg)
Append the message to the message widget.
void setFontSize(int newSize)
void updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
update traffic statistics
void setTrafficGraphRange(int mins)
static bool RPCParseCommandLine(interfaces::Node *node, std::string &strResult, const std::string &strCommand, bool fExecute, std::string *const pstrFilteredOut=nullptr, const WalletModel *wallet_model=nullptr)
Split shell command line into a list of arguments and optionally execute the command(s).
const PlatformStyle *const platformStyle
void setMempoolSize(long numberOfTxs, size_t dynUsage, size_t maxUsage)
Set size (number of transactions and memory usage) of the mempool in the UI.
void updateDetailWidget()
show detailed information on ui about selected node
void showEvent(QShowEvent *event) override
void resizeEvent(QResizeEvent *event) override
static bool RPCExecuteCommandLine(interfaces::Node &node, std::string &strResult, const std::string &strCommand, std::string *const pstrFilteredOut=nullptr, const WalletModel *wallet_model=nullptr)
QString tabTitle(TabTypes tab_type) const
void updateNetworkState()
Update UI with latest network info from model.
void clear(bool keep_prompt=false)
void disconnectSelectedNode()
Disconnect a selected node on the Peers tab.
@ SUBVERSION_COLUMN_WIDTH
QCompleter * autoCompleter
void hideEvent(QHideEvent *event) override
QKeySequence tabShortcut(TabTypes tab_type) const
void showPeersTableContextMenu(const QPoint &point)
Show custom context menu on Peers tab.
QList< NodeId > cachedNodeids
interfaces::Node & m_node
void unbanSelectedNode()
Unban a selected node on the Bans tab.
void updateAlerts(const QString &warnings)
void clearSelectedNode()
clear the selected node
void on_sldGraphRange_valueChanged(int value)
change the time range of the network traffic graph
void setNumConnections(int count)
Set number of connections shown in the UI.
void setNumBlocks(int count, const QDateTime &blockDate, double nVerificationProgress, SyncType synctype)
Set number of blocks and last block date shown in the UI.
ClientModel * clientModel
void banSelectedNode(int bantime)
Ban a selected node on the Peers tab.
void scrollToEnd()
Scroll console view to end.
void keyPressEvent(QKeyEvent *) override
void on_tabWidget_currentChanged(int index)
void setNetworkActive(bool networkActive)
Set network state shown in the UI.
QString cmdBeforeBrowsing
virtual bool eventFilter(QObject *obj, QEvent *event) override
void on_openDebugLogfileButton_clicked()
open the debug.log from the current datadir
void showBanTableContextMenu(const QPoint &point)
Show custom context menu on Bans tab.
void setClientModel(ClientModel *model=nullptr, int bestblock_height=0, int64_t bestblock_date=0, double verification_progress=0.0)
void setTabFocus(enum TabTypes tabType)
set which tab has the focus (is visible)
QByteArray m_peer_widget_header_state
void changeEvent(QEvent *e) override
WalletModel * m_last_wallet_model
void showOrHideBanTableIfRequired()
Hides ban table if no bans are present.
QMenu * banTableContextMenu
void reply(int category, const QString &command)
RPCExecutor(interfaces::Node &node)
interfaces::Node & m_node
void request(const QString &command, const WalletModel *wallet_model)
Opaque base class for timers returned by NewTimerFunc.
void push_back(UniValue val)
const std::string & get_str() const
const UniValue & find_value(std::string_view key) const
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
Interface to Bitcoin wallet from Qt view code.
QString getDisplayName() const
static bool isWalletEnabled()
QString getWalletName() const
Top-level interface for a bitcoin node (bitcoind process).
virtual void rpcSetTimerInterfaceIfUnset(RPCTimerInterface *iface)=0
Set RPC timer interface if unset.
virtual bool disconnectById(NodeId id)=0
Disconnect node by id.
virtual bool ban(const CNetAddr &net_addr, int64_t ban_time_offset)=0
Ban node.
virtual std::vector< std::string > listRpcCommands()=0
List rpc commands.
virtual void rpcUnsetTimerInterface(RPCTimerInterface *iface)=0
Unset RPC timer interface.
virtual bool getNetworkActive()=0
Get network active.
virtual bool disconnectByAddress(const CNetAddr &net_addr)=0
Disconnect node by address.
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
std::string TransportTypeAsString(TransportProtocolType transport_type)
Convert TransportProtocolType enum to a string value.
QString NetworkToQString(Network net)
Convert enum Network to QString.
QString HtmlEscape(const QString &str, bool fMultiLine)
QList< QModelIndex > getEntryData(const QAbstractItemView *view, int column)
Return a field of the currently selected entry as a QString.
QFont fixedPitchFont(bool use_embedded_font)
QString formatBytes(uint64_t bytes)
QString formatDurationStr(std::chrono::seconds dur)
Convert seconds into a QString with days, hours, mins, secs.
void AddButtonShortcut(QAbstractButton *button, const QKeySequence &shortcut)
Connects an additional shortcut to a QAbstractButton.
void handleCloseWindowShortcut(QWidget *w)
void copyEntryData(const QAbstractItemView *view, int column, int role)
Copy a field of the currently selected entry of a view to the clipboard.
QString formatPingTime(std::chrono::microseconds ping_time)
Format a CNodeStats.m_last_ping_time into a user-readable string or display N/A, if 0.
QString ConnectionTypeToQString(ConnectionType conn_type, bool prepend_direction)
Convert enum ConnectionType to QString.
QString formatServicesStr(quint64 mask)
Format CNodeStats.nServices bitmask into a user-readable string.
QString formatTimeOffset(int64_t time_offset)
Format a CNodeStateStats.time_offset into a user-readable string.
bool IsEscapeOrBack(int key)
void ThreadRename(const std::string &)
Rename a thread both in terms of an internal (in-memory) name as well as its system thread name.
auto Join(const C &container, const S &separator, UnaryOp unary_op)
Join all container items.
const std::vector< std::string > CONNECTION_TYPE_DOC
const std::vector< std::string > TRANSPORT_TYPE_DOC
const int INITIAL_TRAFFIC_GRAPH_MINS
const struct @8 ICON_MAPPING[]
const QSize FONT_RANGE(4, 40)
const int CONSOLE_HISTORY
static QString categoryClass(int category)
const char fontSizeSettingsKey[]