Bitcoin ABC 0.26.3
P2P Digital Currency
Loading...
Searching...
No Matches
rpcconsole.cpp
Go to the documentation of this file.
1// Copyright (c) 2011-2019 The Bitcoin Core developers
2// Distributed under the MIT software license, see the accompanying
3// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4
5#if defined(HAVE_CONFIG_H)
6#include <config/bitcoin-config.h>
7#endif
8
9#include <qt/rpcconsole.h>
10
11#include <chainparams.h>
12#include <common/system.h>
13#include <config.h>
14#include <interfaces/node.h>
15#include <netbase.h>
16#include <qt/bantablemodel.h>
17#include <qt/clientmodel.h>
18#include <qt/forms/ui_debugwindow.h>
19#include <qt/platformstyle.h>
20#include <qt/walletmodel.h>
21#include <rpc/client.h>
22#include <rpc/server.h>
23#include <util/strencodings.h>
24#include <util/threadnames.h>
25
26#ifdef ENABLE_WALLET
27#include <wallet/bdb.h>
28#include <wallet/db.h>
29#include <wallet/wallet.h>
30#endif
31
32#include <univalue.h>
33
34#include <QFont>
35#include <QKeyEvent>
36#include <QMenu>
37#include <QMessageBox>
38#include <QScreen>
39#include <QScrollBar>
40#include <QSettings>
41#include <QString>
42#include <QStringList>
43#include <QTime>
44#include <QTimer>
45
46const int CONSOLE_HISTORY = 50;
48const QSize FONT_RANGE(4, 40);
49const char fontSizeSettingsKey[] = "consoleFontSize";
50
51const struct {
52 const char *url;
53 const char *source;
54} ICON_MAPPING[] = {{"cmd-request", ":/icons/tx_input"},
55 {"cmd-reply", ":/icons/tx_output"},
56 {"cmd-error", ":/icons/tx_output"},
57 {"misc", ":/icons/tx_inout"},
58 {nullptr, nullptr}};
59
60namespace {
61
62// don't add private key handling cmd's to the history
63const QStringList historyFilter = QStringList() << "importprivkey"
64 << "importmulti"
65 << "sethdseed"
66 << "signmessagewithprivkey"
67 << "signrawtransactionwithkey"
68 << "walletpassphrase"
69 << "walletpassphrasechange"
70 << "encryptwallet";
71} // namespace
72
73/* Object for executing console RPC commands in a separate thread.
74 */
75class RPCExecutor : public QObject {
77public:
79
80public Q_SLOTS:
81 void request(const QString &command, const WalletModel *wallet_model);
82
84 void reply(int category, const QString &command);
85
86private:
88};
89
93class QtRPCTimerBase : public QObject, public RPCTimerBase {
95public:
96 QtRPCTimerBase(std::function<void()> &_func, int64_t millis) : func(_func) {
97 timer.setSingleShot(true);
98 connect(&timer, &QTimer::timeout, [this] { func(); });
99 timer.start(millis);
100 }
102
103private:
105 std::function<void()> func;
106};
107
109public:
111 const char *Name() override { return "Qt"; }
112 RPCTimerBase *NewTimer(std::function<void()> &func,
113 int64_t millis) override {
114 return new QtRPCTimerBase(func, millis);
115 }
116};
117
118#include <qt/rpcconsole.moc>
119
147 std::string &strResult,
148 const std::string &strCommand,
149 const bool fExecute,
150 std::string *const pstrFilteredOut,
151 const WalletModel *wallet_model) {
152 std::vector<std::vector<std::string>> stack;
153 stack.push_back(std::vector<std::string>());
154
155 enum CmdParseState {
166 } state = STATE_EATING_SPACES;
167 std::string curarg;
169 unsigned nDepthInsideSensitive = 0;
170 size_t filter_begin_pos = 0, chpos;
171 std::vector<std::pair<size_t, size_t>> filter_ranges;
172
173 auto add_to_current_stack = [&](const std::string &strArg) {
174 if (stack.back().empty() && (!nDepthInsideSensitive) &&
175 historyFilter.contains(QString::fromStdString(strArg),
176 Qt::CaseInsensitive)) {
179 }
180 // Make sure stack is not empty before adding something
181 if (stack.empty()) {
182 stack.push_back(std::vector<std::string>());
183 }
184 stack.back().push_back(strArg);
185 };
186
187 auto close_out_params = [&]() {
189 if (!--nDepthInsideSensitive) {
191 filter_ranges.push_back(
192 std::make_pair(filter_begin_pos, chpos));
194 }
195 }
196 stack.pop_back();
197 };
198
199 std::string strCommandTerminated = strCommand;
200 if (strCommandTerminated.back() != '\n') {
201 strCommandTerminated += "\n";
202 }
203 for (chpos = 0; chpos < strCommandTerminated.size(); ++chpos) {
205 switch (state) {
208 bool breakParsing = true;
209 switch (ch) {
210 case '[':
211 curarg.clear();
213 break;
214 default:
215 if (state == STATE_COMMAND_EXECUTED_INNER) {
216 if (ch != ']') {
217 // append char to the current argument (which is
218 // also used for the query command)
219 curarg += ch;
220 break;
221 }
222 if (curarg.size() && fExecute) {
223 // if we have a value query, query arrays with
224 // index and objects with a string key
226 if (lastResult.isArray()) {
227 for (char argch : curarg) {
228 if (!IsDigit(argch)) {
229 throw std::runtime_error(
230 "Invalid result query");
231 }
232 }
233 subelement =
234 lastResult[atoi(curarg.c_str())];
235 } else if (lastResult.isObject()) {
236 subelement = lastResult.find_value(curarg);
237 } else {
238 // no array or object: abort
239 throw std::runtime_error(
240 "Invalid result query");
241 }
243 }
244
246 break;
247 }
248 // don't break parsing when the char is required for the
249 // next argument
250 breakParsing = false;
251
252 // pop the stack and return the result to the current
253 // command arguments
255
256 // don't stringify the json in case of a string to avoid
257 // doublequotes
258 if (lastResult.isStr()) {
259 curarg = lastResult.get_str();
260 } else {
261 curarg = lastResult.write(2);
262 }
263
264 // if we have a non empty result, use it as stack
265 // argument otherwise as general result
266 if (curarg.size()) {
267 if (stack.size()) {
269 } else {
271 }
272 }
273 curarg.clear();
274 // assume eating space state
275 state = STATE_EATING_SPACES;
276 }
277
278 if (breakParsing) {
279 break;
280 }
281 }
282 // FALLTHROUGH
283 case STATE_ARGUMENT: // In or after argument
286 case STATE_EATING_SPACES: // Handle runs of whitespace
287 switch (ch) {
288 case '"':
289 state = STATE_DOUBLEQUOTED;
290 break;
291 case '\'':
292 state = STATE_SINGLEQUOTED;
293 break;
294 case '\\':
295 state = STATE_ESCAPE_OUTER;
296 break;
297 case '(':
298 case ')':
299 case '\n':
300 if (state == STATE_EATING_SPACES_IN_ARG) {
301 throw std::runtime_error("Invalid Syntax");
302 }
303 if (state == STATE_ARGUMENT) {
304 if (ch == '(' && stack.size() &&
305 stack.back().size() > 0) {
308 }
309 stack.push_back(std::vector<std::string>());
310 }
311
312 // don't allow commands after executed commands on
313 // baselevel
314 if (!stack.size()) {
315 throw std::runtime_error("Invalid Syntax");
316 }
317
319 curarg.clear();
321 }
322 if ((ch == ')' || ch == '\n') && stack.size() > 0) {
323 if (fExecute) {
324 // Convert argument list to JSON objects in
325 // method-dependent way, and pass it along with
326 // the method name to the dispatcher.
327 UniValue params = RPCConvertValues(
328 stack.back()[0],
329 std::vector<std::string>(
330 stack.back().begin() + 1,
331 stack.back().end()));
332 std::string method = stack.back()[0];
333 std::string uri;
334
335#ifdef ENABLE_WALLET
336 if (wallet_model) {
338 QUrl::toPercentEncoding(
339 wallet_model->getWalletName());
340 uri = "/wallet/" +
341 std::string(encodedName.constData(),
342 encodedName.length());
343 }
344#endif
345
346 assert(node);
347 lastResult = node->executeRpc(
348 GetConfig(), method, params, uri);
349 }
350
352 curarg.clear();
353 }
354 break;
355 case ' ':
356 case ',':
357 case '\t':
358 if (state == STATE_EATING_SPACES_IN_ARG &&
359 curarg.empty() && ch == ',') {
360 throw std::runtime_error("Invalid Syntax");
361 } else if (state == STATE_ARGUMENT) {
362 // Space ends argument
364 curarg.clear();
365 }
366 if ((state == STATE_EATING_SPACES_IN_BRACKETS ||
367 state == STATE_ARGUMENT) &&
368 ch == ',') {
370 break;
371 }
372 state = STATE_EATING_SPACES;
373 break;
374 default:
375 curarg += ch;
376 state = STATE_ARGUMENT;
377 }
378 break;
379 case STATE_SINGLEQUOTED: // Single-quoted string
380 switch (ch) {
381 case '\'':
382 state = STATE_ARGUMENT;
383 break;
384 default:
385 curarg += ch;
386 }
387 break;
388 case STATE_DOUBLEQUOTED: // Double-quoted string
389 switch (ch) {
390 case '"':
391 state = STATE_ARGUMENT;
392 break;
393 case '\\':
395 break;
396 default:
397 curarg += ch;
398 }
399 break;
400 case STATE_ESCAPE_OUTER: // '\' outside quotes
401 curarg += ch;
402 state = STATE_ARGUMENT;
403 break;
404 case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
405 if (ch != '"' && ch != '\\') {
406 // keep '\' for everything but the quote and '\' itself
407 curarg += '\\';
408 }
409 curarg += ch;
410 state = STATE_DOUBLEQUOTED;
411 break;
412 }
413 }
414 if (pstrFilteredOut) {
415 if (STATE_COMMAND_EXECUTED == state) {
416 assert(!stack.empty());
418 }
420 for (auto i = filter_ranges.rbegin(); i != filter_ranges.rend(); ++i) {
421 pstrFilteredOut->replace(i->first, i->second - i->first, "(…)");
422 }
423 }
424
425 // final state
426 switch (state) {
428 if (lastResult.isStr()) {
429 strResult = lastResult.get_str();
430 } else {
431 strResult = lastResult.write(2);
432 }
433 // FALLTHROUGH
434 case STATE_ARGUMENT:
436 return true;
437 default: // ERROR to end in one of the other states
438 return false;
439 }
440}
441
443 const WalletModel *wallet_model) {
444 try {
445 std::string result;
446 std::string executableCommand = command.toStdString() + "\n";
447
448 // Catch the console-only-help command before RPC call is executed and
449 // reply with help text as-if a RPC reply.
450 if (executableCommand == "help-console\n") {
453 QString(("\n"
454 "This console accepts RPC commands using the standard "
455 "syntax.\n"
456 " example: getblockhash 0\n\n"
457
458 "This console can also accept RPC commands using "
459 "parenthesized syntax.\n"
460 " example: getblockhash(0)\n\n"
461
462 "Commands may be nested when specified with the "
463 "parenthesized syntax.\n"
464 " example: getblock(getblockhash(0) 1)\n\n"
465
466 "A space or a comma can be used to delimit arguments "
467 "for either syntax.\n"
468 " example: getblockhash 0\n"
469 " getblockhash,0\n\n"
470
471 "Named results can be queried with a non-quoted key "
472 "string in brackets.\n"
473 " example: getblock(getblockhash(0) true)[tx]\n\n"
474
475 "Results without keys can be queried using an integer "
476 "in brackets.\n"
477 " example: "
478 "getblock(getblockhash(0),true)[tx][0]\n\n")));
479 return;
480 }
482 m_node, result, executableCommand, nullptr, wallet_model)) {
484 QString("Parse error: unbalanced ' or \""));
485 return;
486 }
487
488 Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(result));
489 } catch (UniValue &objError) {
490 // Nice formatting for standard-format error
491 try {
492 int code = objError.find_value("code").getInt<int>();
493 std::string message = objError.find_value("message").get_str();
495 QString::fromStdString(message) + " (code " +
496 QString::number(code) + ")");
497 } catch (const std::runtime_error &) {
498 // raised when converting to invalid type, i.e. missing code or
499 // message. Show raw JSON object.
501 QString::fromStdString(objError.write()));
502 }
503 } catch (const std::exception &e) {
505 QString("Error: ") + QString::fromStdString(e.what()));
506 }
507}
508
510 const PlatformStyle *_platformStyle, QWidget *parent)
511 : QWidget(parent), m_node(node), ui(new Ui::RPCConsole),
512 platformStyle(_platformStyle) {
513 ui->setupUi(this);
515 if (!restoreGeometry(
516 settings.value("RPCConsoleWindowGeometry").toByteArray())) {
517 // Restore failed (perhaps missing setting), center the window
518 move(QGuiApplication::primaryScreen()->availableGeometry().center() -
520 }
521
523 const QString hb_list{"<ul><li>\"" + tr("To") + "\" – " +
524 tr("we selected the peer for high bandwidth relay") +
525 "</li><li>\"" + tr("From") + "\" – " +
526 tr("the peer selected us for high bandwidth relay") +
527 "</li><li>\"" + tr("No") + "\" – " +
528 tr("no high bandwidth relay selected") +
529 "</li></ul>"};
530 ui->peerHighBandwidthLabel->setToolTip(
531 ui->peerHighBandwidthLabel->toolTip().arg(hb_list));
532 ui->dataDir->setToolTip(
533 ui->dataDir->toolTip().arg(QString(nonbreaking_hyphen) + "datadir"));
534 ui->blocksDir->setToolTip(ui->blocksDir->toolTip().arg(
535 QString(nonbreaking_hyphen) + "blocksdir"));
536 ui->openDebugLogfileButton->setToolTip(
537 ui->openDebugLogfileButton->toolTip().arg(PACKAGE_NAME));
538
540 ui->openDebugLogfileButton->setIcon(
541 platformStyle->SingleColorIcon(":/icons/export"));
542 }
543 ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
544 ui->fontBiggerButton->setIcon(
545 platformStyle->SingleColorIcon(":/icons/fontbigger"));
546 ui->fontSmallerButton->setIcon(
547 platformStyle->SingleColorIcon(":/icons/fontsmaller"));
548
549 // Install event filter for up and down arrow
550 ui->lineEdit->installEventFilter(this);
551 ui->lineEdit->setMaxLength(16 * 1024 * 1024);
552 ui->messagesWidget->installEventFilter(this);
553
554 connect(ui->clearButton, &QPushButton::clicked, this, &RPCConsole::clear);
555 connect(ui->fontBiggerButton, &QPushButton::clicked, this,
557 connect(ui->fontSmallerButton, &QPushButton::clicked, this,
559 connect(ui->btnClearTrafficGraph, &QPushButton::clicked, ui->trafficGraph,
561
562 // disable the wallet selector by default
563 ui->WalletSelector->setVisible(false);
564 ui->WalletSelectorLabel->setVisible(false);
565
566// set library version labels
567#ifdef ENABLE_WALLET
568 ui->berkeleyDBVersion->setText(
569 QString::fromStdString(BerkeleyDatabaseVersion()));
570#else
571 ui->label_berkeleyDBVersion->hide();
572 ui->berkeleyDBVersion->hide();
573#endif
574 // Register RPC timer interface
576 // avoid accidentally overwriting an existing, non QTThread
577 // based timer interface
579
582
584 settings.value(fontSizeSettingsKey, QFont().pointSize()).toInt();
585 clear();
586
588}
589
592 settings.setValue("RPCConsoleWindowGeometry", saveGeometry());
594 delete rpcTimerInterface;
595 delete ui;
596}
597
598bool RPCConsole::eventFilter(QObject *obj, QEvent *event) {
599 // Special key handling
600 if (event->type() == QEvent::KeyPress) {
601 QKeyEvent *keyevt = static_cast<QKeyEvent *>(event);
602 int key = keyevt->key();
603 Qt::KeyboardModifiers mod = keyevt->modifiers();
604 switch (key) {
605 case Qt::Key_Up:
606 if (obj == ui->lineEdit) {
607 browseHistory(-1);
608 return true;
609 }
610 break;
611 case Qt::Key_Down:
612 if (obj == ui->lineEdit) {
613 browseHistory(1);
614 return true;
615 }
616 break;
617 case Qt::Key_PageUp: /* pass paging keys to messages widget */
618 case Qt::Key_PageDown:
619 if (obj == ui->lineEdit) {
620 QApplication::postEvent(ui->messagesWidget,
621 new QKeyEvent(*keyevt));
622 return true;
623 }
624 break;
625 case Qt::Key_Return:
626 case Qt::Key_Enter:
627 // forward these events to lineEdit
628 if (obj == autoCompleter->popup()) {
629 QApplication::postEvent(ui->lineEdit,
630 new QKeyEvent(*keyevt));
631 return true;
632 }
633 break;
634 default:
635 // Typing in messages widget brings focus to line edit, and
636 // redirects key there. Exclude most combinations and keys that
637 // emit no text, except paste shortcuts.
638 if (obj == ui->messagesWidget &&
639 ((!mod && !keyevt->text().isEmpty() &&
640 key != Qt::Key_Tab) ||
641 ((mod & Qt::ControlModifier) && key == Qt::Key_V) ||
642 ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert))) {
643 ui->lineEdit->setFocus();
644 QApplication::postEvent(ui->lineEdit,
645 new QKeyEvent(*keyevt));
646 return true;
647 }
648 }
649 }
650 return QWidget::eventFilter(obj, event);
651}
652
655 double verification_progress) {
656 clientModel = model;
657
658 bool wallet_enabled{false};
659#ifdef ENABLE_WALLET
661#endif // ENABLE_WALLET
662 if (model && !wallet_enabled) {
663 // Show warning, for example if this is a prerelease version
667 }
668
669 ui->trafficGraph->setClientModel(model);
670 if (model && clientModel->getPeerTableModel() &&
672 // Keep up to date with client
676
677 setNumBlocks(bestblock_height, QDateTime::fromTime_t(bestblock_date),
678 verification_progress, SyncType::BLOCK_SYNC);
681
685
687 updateTrafficStats(node.getTotalBytesRecv(), node.getTotalBytesSent());
690
693
694 // set up peer table
695 ui->peerWidget->setModel(model->getPeerTableModel());
696 ui->peerWidget->verticalHeader()->hide();
697 ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
698 ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
699 ui->peerWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
700 ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu);
701 ui->peerWidget->setColumnWidth(PeerTableModel::Address,
703 ui->peerWidget->setColumnWidth(PeerTableModel::Subversion,
705 ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH);
706 ui->peerWidget->horizontalHeader()->setStretchLastSection(true);
707
708 // create peer table context menu actions
709 QAction *disconnectAction = new QAction(tr("&Disconnect"), this);
711 new QAction(tr("Ban for") + " " + tr("1 &hour"), this);
713 new QAction(tr("Ban for") + " " + tr("1 &day"), this);
715 new QAction(tr("Ban for") + " " + tr("1 &week"), this);
717 new QAction(tr("Ban for") + " " + tr("1 &year"), this);
718
719 // create peer table context menu
720 peersTableContextMenu = new QMenu(this);
726
727 connect(banAction1h, &QAction::triggered,
728 [this] { banSelectedNode(60 * 60); });
729 connect(banAction24h, &QAction::triggered,
730 [this] { banSelectedNode(60 * 60 * 24); });
731 connect(banAction7d, &QAction::triggered,
732 [this] { banSelectedNode(60 * 60 * 24 * 7); });
733 connect(banAction365d, &QAction::triggered,
734 [this] { banSelectedNode(60 * 60 * 24 * 365); });
735
736 // peer table context menu signals
737 connect(ui->peerWidget, &QTableView::customContextMenuRequested, this,
739 connect(disconnectAction, &QAction::triggered, this,
741
742 // peer table signal handling - update peer details when selecting new
743 // node
744 connect(ui->peerWidget->selectionModel(),
745 &QItemSelectionModel::selectionChanged, this,
747 // peer table signal handling - update peer details when new nodes are
748 // added to the model
749 connect(model->getPeerTableModel(), &PeerTableModel::layoutChanged,
751 // peer table signal handling - cache selected node ids
752 connect(model->getPeerTableModel(),
753 &PeerTableModel::layoutAboutToBeChanged, this,
755
756 // set up ban table
757 ui->banlistWidget->setModel(model->getBanTableModel());
758 ui->banlistWidget->verticalHeader()->hide();
759 ui->banlistWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
760 ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
761 ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection);
762 ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu);
763 ui->banlistWidget->setColumnWidth(BanTableModel::Address,
765 ui->banlistWidget->setColumnWidth(BanTableModel::Bantime,
767 ui->banlistWidget->horizontalHeader()->setStretchLastSection(true);
768
769 // create ban table context menu action
770 QAction *unbanAction = new QAction(tr("&Unban"), this);
771
772 // create ban table context menu
773 banTableContextMenu = new QMenu(this);
775
776 // ban table context menu signals
777 connect(ui->banlistWidget, &QTableView::customContextMenuRequested,
779 connect(unbanAction, &QAction::triggered, this,
781
782 // ban table signal handling - clear peer details when clicking a peer
783 // in the ban table
784 connect(ui->banlistWidget, &QTableView::clicked, this,
786 // ban table signal handling - ensure ban table is shown or hidden (if
787 // empty)
788 connect(model->getBanTableModel(), &BanTableModel::layoutChanged, this,
791
792 // Provide initial values
793 ui->clientVersion->setText(model->formatFullVersion());
794 ui->clientUserAgent->setText(model->formatSubVersion());
795 ui->dataDir->setText(model->dataDir());
796 ui->blocksDir->setText(model->blocksDir());
797 ui->startupTime->setText(model->formatClientStartupTime());
798 ui->networkName->setText(
799 QString::fromStdString(Params().NetworkIDString()));
800
801 // Setup autocomplete and attach it
803 std::vector<std::string> commandList = m_node.listRpcCommands();
804 for (size_t i = 0; i < commandList.size(); ++i) {
805 wordList << commandList[i].c_str();
806 wordList << ("help " + commandList[i]).c_str();
807 }
808
809 wordList << "help-console";
810 wordList.sort();
811 autoCompleter = new QCompleter(wordList, this);
812 autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel);
813 // ui->lineEdit is initially disabled because running commands is only
814 // possible from now on.
815 ui->lineEdit->setEnabled(true);
816 ui->lineEdit->setCompleter(autoCompleter);
817 autoCompleter->popup()->installEventFilter(this);
818 // Start thread to execute RPC commands.
820 }
821 if (!model) {
822 // Client model is being set to 0, this means shutdown() is about to be
823 // called.
824 thread.quit();
825 thread.wait();
826 }
827}
828
829#ifdef ENABLE_WALLET
830void RPCConsole::addWallet(WalletModel *const walletModel) {
831 // use name for text and wallet model for internal data object (to allow to
832 // move to a wallet id later)
833 ui->WalletSelector->addItem(walletModel->getDisplayName(),
834 QVariant::fromValue(walletModel));
835 if (ui->WalletSelector->count() == 2 && !isVisible()) {
836 // First wallet added, set to default so long as the window isn't
837 // presently visible (and potentially in use)
838 ui->WalletSelector->setCurrentIndex(1);
839 }
840 if (ui->WalletSelector->count() > 2) {
841 ui->WalletSelector->setVisible(true);
842 ui->WalletSelectorLabel->setVisible(true);
843 }
844}
845
846void RPCConsole::removeWallet(WalletModel *const walletModel) {
847 ui->WalletSelector->removeItem(
848 ui->WalletSelector->findData(QVariant::fromValue(walletModel)));
849 if (ui->WalletSelector->count() == 2) {
850 ui->WalletSelector->setVisible(false);
851 ui->WalletSelectorLabel->setVisible(false);
852 }
853}
854#endif
855
856static QString categoryClass(int category) {
857 switch (category) {
859 return "cmd-request";
860 break;
862 return "cmd-reply";
863 break;
865 return "cmd-error";
866 break;
867 default:
868 return "misc";
869 }
870}
871
875
879
882
883 // don't allow an insane font size
884 if (newSize < FONT_RANGE.width() || newSize > FONT_RANGE.height()) {
885 return;
886 }
887
888 // temp. store the console content
889 QString str = ui->messagesWidget->toHtml();
890
891 // replace font tags size in current content
892 str.replace(QString("font-size:%1pt").arg(consoleFontSize),
893 QString("font-size:%1pt").arg(newSize));
894
895 // store the new font size
898
899 // clear console (reset icon sizes, default stylesheet) and re-add the
900 // content
901 float oldPosFactor = 1.0 /
902 ui->messagesWidget->verticalScrollBar()->maximum() *
903 ui->messagesWidget->verticalScrollBar()->value();
904 clear(false);
905 ui->messagesWidget->setHtml(str);
906 ui->messagesWidget->verticalScrollBar()->setValue(
907 oldPosFactor * ui->messagesWidget->verticalScrollBar()->maximum());
908}
909
911 ui->messagesWidget->clear();
912 if (clearHistory) {
913 history.clear();
914 historyPtr = 0;
915 }
916 ui->lineEdit->clear();
917 ui->lineEdit->setFocus();
918
919 // Add smoothly scaled icon images.
920 // (when using width/height on an img, Qt uses nearest instead of linear
921 // interpolation)
922 for (int i = 0; ICON_MAPPING[i].url; ++i) {
923 ui->messagesWidget->document()->addResource(
924 QTextDocument::ImageResource, QUrl(ICON_MAPPING[i].url),
926 .scaled(QSize(consoleFontSize * 2, consoleFontSize * 2),
927 Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
928 }
929
930 // Set default style sheet
932 ui->messagesWidget->document()->setDefaultStyleSheet(
933 QString("table { }"
934 "td.time { color: #808080; font-size: %2; padding-top: 3px; } "
935 "td.message { font-family: %1; font-size: %2; "
936 "white-space:pre-wrap; } "
937 "td.cmd-request { color: #006060; } "
938 "td.cmd-error { color: red; } "
939 ".secwarning { color: red; }"
940 "b { color: #006060; } ")
941 .arg(fixedFontInfo.family(), QString("%1pt").arg(consoleFontSize)));
942
943#ifdef Q_OS_MAC
944 QString clsKey = "(⌘)-L";
945#else
946 QString clsKey = "Ctrl-L";
947#endif
948
950 (tr("Welcome to the %1 RPC console.").arg(PACKAGE_NAME) + "<br>" +
951 tr("Use up and down arrows to navigate history, and "
952 "%1 to clear screen.")
953 .arg("<b>" + clsKey + "</b>") +
954 "<br>" +
955 tr("Type %1 for an overview of available commands.")
956 .arg("<b>help</b>") +
957 "<br>" +
958 tr("For more information on using this console type %1.")
959 .arg("<b>help-console</b>") +
960 "<br><span class=\"secwarning\"><br>" +
961 tr("WARNING: Scammers have been active, telling users to type "
962 "commands here, stealing their wallet contents. Do not use "
963 "this console without fully understanding the ramifications "
964 "of a command.") +
965 "</span>"),
966 true);
967}
968
970 if (windowType() != Qt::Widget && event->key() == Qt::Key_Escape) {
971 close();
972 }
973}
974
975void RPCConsole::message(int category, const QString &message, bool html) {
976 QTime time = QTime::currentTime();
977 QString timeString = time.toString();
978 QString out;
979 out += "<table><tr><td class=\"time\" width=\"65\">" + timeString + "</td>";
980 out += "<td class=\"icon\" width=\"32\"><img src=\"" +
981 categoryClass(category) + "\"></td>";
982 out += "<td class=\"message " + categoryClass(category) +
983 "\" valign=\"middle\">";
984 if (html) {
985 out += message;
986 } else {
987 out += GUIUtil::HtmlEscape(message, false);
988 }
989 out += "</td></tr></table>";
990 ui->messagesWidget->append(out);
991}
992
995 QString::number(clientModel->getNumConnections()) + " (";
996 connections += tr("In:") + " " +
997 QString::number(clientModel->getNumConnections(
999 " / ";
1000 connections += tr("Out:") + " " +
1001 QString::number(clientModel->getNumConnections(
1003 ")";
1004
1005 if (!clientModel->node().getNetworkActive()) {
1006 connections += " (" + tr("Network activity disabled") + ")";
1007 }
1008
1009 ui->numberOfConnections->setText(connections);
1010}
1011
1013 if (!clientModel) {
1014 return;
1015 }
1016
1018}
1019
1023
1027 ui->numberOfBlocks->setText(QString::number(count));
1028 ui->lastBlockTime->setText(blockDate.toString());
1029 }
1030}
1031
1033 ui->mempoolNumberTxs->setText(QString::number(numberOfTxs));
1034
1035 if (dynUsage < 1000000) {
1036 ui->mempoolSize->setText(QString::number(dynUsage / 1000.0, 'f', 2) +
1037 " KB");
1038 } else {
1039 ui->mempoolSize->setText(QString::number(dynUsage / 1000000.0, 'f', 2) +
1040 " MB");
1041 }
1042}
1043
1045 QString cmd = ui->lineEdit->text();
1046
1047 if (!cmd.isEmpty()) {
1048 std::string strFilteredCmd;
1049 try {
1050 std::string dummy;
1051 if (!RPCParseCommandLine(nullptr, dummy, cmd.toStdString(), false,
1052 &strFilteredCmd)) {
1053 // Failed to parse command, so we cannot even filter it for the
1054 // history
1055 throw std::runtime_error("Invalid command line");
1056 }
1057 } catch (const std::exception &e) {
1058 QMessageBox::critical(this, "Error",
1059 QString("Error: ") +
1060 QString::fromStdString(e.what()));
1061 return;
1062 }
1063
1064 ui->lineEdit->clear();
1065
1067
1068#ifdef ENABLE_WALLET
1070 ui->WalletSelector->currentData().value<WalletModel *>();
1071
1073 if (wallet_model) {
1074 message(CMD_REQUEST, tr("Executing command using \"%1\" wallet")
1075 .arg(wallet_model->getWalletName()));
1076 } else {
1078 tr("Executing command without any wallet"));
1079 }
1081 }
1082#endif
1083
1084 message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
1086
1087 cmd = QString::fromStdString(strFilteredCmd);
1088
1089 // Remove command, if already in history
1090 history.removeOne(cmd);
1091 // Append command to history
1092 history.append(cmd);
1093 // Enforce maximum history size
1094 while (history.size() > CONSOLE_HISTORY) {
1095 history.removeFirst();
1096 }
1097 // Set pointer to end of history
1098 historyPtr = history.size();
1099
1100 // Scroll console view to end
1101 scrollToEnd();
1102 }
1103}
1104
1106 // store current text when start browsing through the history
1107 if (historyPtr == history.size()) {
1108 cmdBeforeBrowsing = ui->lineEdit->text();
1109 }
1110
1111 historyPtr += offset;
1112 if (historyPtr < 0) {
1113 historyPtr = 0;
1114 }
1115 if (historyPtr > history.size()) {
1116 historyPtr = history.size();
1117 }
1118 QString cmd;
1119 if (historyPtr < history.size()) {
1120 cmd = history.at(historyPtr);
1121 } else if (!cmdBeforeBrowsing.isNull()) {
1123 }
1124 ui->lineEdit->setText(cmd);
1125}
1126
1129 executor->moveToThread(&thread);
1130
1131 // Replies from executor object must go to this object
1133 static_cast<void (RPCConsole::*)(int, const QString &)>(
1135
1136 // Requests from this object must go to executor
1138
1139 // Make sure executor object is deleted in its own thread
1140 connect(&thread, &QThread::finished, executor, &RPCExecutor::deleteLater);
1141
1142 // Default implementation of QThread::run() simply spins up an event loop in
1143 // the thread, which is what we want.
1144 thread.start();
1145 QTimer::singleShot(0, executor,
1146 []() { util::ThreadRename("qt-rpcconsole"); });
1147}
1148
1150 if (ui->tabWidget->widget(index) == ui->tab_console) {
1151 ui->lineEdit->setFocus();
1152 }
1153}
1154
1158
1160 QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
1161 scrollbar->setValue(scrollbar->maximum());
1162}
1163
1165 const int multiplier = 5; // each position on the slider represents 5 min
1166 int mins = value * multiplier;
1168}
1169
1171 ui->trafficGraph->setGraphRangeMins(mins);
1172 ui->lblGraphRange->setText(
1173 GUIUtil::formatDurationStr(std::chrono::minutes{mins}));
1174}
1175
1181
1184 ui->peerWidget->selectionModel()->selectedIndexes();
1185 cachedNodeids.clear();
1186 for (int i = 0; i < selected.size(); i++) {
1187 const CNodeCombinedStats *stats =
1189 selected.at(i).row());
1190 cachedNodeids.append(stats->nodeStats.nodeid);
1191 }
1192}
1193
1196 return;
1197 }
1198
1199 bool fUnselect = false;
1200 bool fReselect = false;
1201
1202 // no node selected yet
1203 if (cachedNodeids.empty()) {
1204 return;
1205 }
1206
1207 // find the currently selected row
1208 int selectedRow = -1;
1210 ui->peerWidget->selectionModel()->selectedIndexes();
1211 if (!selectedModelIndex.isEmpty()) {
1212 selectedRow = selectedModelIndex.first().row();
1213 }
1214
1215 // check if our detail node has a row in the table (it may not necessarily
1216 // be at selectedRow since its position can change after a layout change)
1217 int detailNodeRow =
1219
1220 if (detailNodeRow < 0) {
1221 // detail node disappeared from table (node disconnected)
1222 fUnselect = true;
1223 } else {
1224 if (detailNodeRow != selectedRow) {
1225 // detail node moved position
1226 fUnselect = true;
1227 fReselect = true;
1228 }
1229 }
1230
1231 if (fUnselect && selectedRow >= 0) {
1233 }
1234
1235 if (fReselect) {
1236 for (int i = 0; i < cachedNodeids.size(); i++) {
1237 ui->peerWidget->selectRow(
1239 cachedNodeids.at(i)));
1240 }
1241 }
1242
1244}
1245
1248 auto selection_model = ui->peerWidget->selectionModel();
1249 if (selection_model) {
1250 selected_rows = selection_model->selectedRows();
1251 }
1253 selected_rows.size() != 1) {
1254 ui->detailWidget->hide();
1255 ui->peerHeading->setText(
1256 tr("Select a peer to view detailed information."));
1257 return;
1258 }
1259 const CNodeCombinedStats *stats =
1261 selected_rows.first().row());
1262 // update the detail ui with latest node information
1264 QString::fromStdString(stats->nodeStats.m_addr_name) + " ");
1266 tr("(peer id: %1)").arg(QString::number(stats->nodeStats.nodeid));
1267 if (!stats->nodeStats.addrLocal.empty()) {
1268 peerAddrDetails += "<br />" + tr("via %1").arg(QString::fromStdString(
1269 stats->nodeStats.addrLocal));
1270 }
1271 ui->peerHeading->setText(peerAddrDetails);
1274 bip152_hb_settings += "To";
1275 }
1277 bip152_hb_settings += (bip152_hb_settings == "" ? "From" : "/From");
1278 }
1279 if (bip152_hb_settings == "") {
1280 bip152_hb_settings = "No";
1281 }
1282 ui->peerHighBandwidth->setText(bip152_hb_settings);
1284 ui->peerConnTime->setText(
1286 ui->peerLastBlock->setText(
1288 ui->peerLastTx->setText(
1290 ui->peerLastSend->setText(
1292 ui->peerLastRecv->setText(
1294 ui->peerBytesSent->setText(
1296 ui->peerBytesRecv->setText(
1298 ui->peerPingTime->setText(
1300 ui->peerMinPing->setText(
1302 ui->timeoffset->setText(
1304 ui->peerVersion->setText(QString::number(stats->nodeStats.nVersion));
1305 ui->peerSubversion->setText(
1306 QString::fromStdString(stats->nodeStats.cleanSubVer));
1307 ui->peerDirection->setText(stats->nodeStats.fInbound ? tr("Inbound")
1308 : tr("Outbound"));
1309 ui->peerNetwork->setText(
1312 ui->peerPermissions->setText(tr("N/A"));
1313 } else {
1315 for (const auto &permission :
1317 permissions.append(QString::fromStdString(permission));
1318 }
1319 ui->peerPermissions->setText(permissions.join(" & "));
1320 }
1321 ui->peerMappedAS->setText(
1322 stats->nodeStats.m_mapped_as != 0
1323 ? QString::number(stats->nodeStats.m_mapped_as)
1324 : tr("N/A"));
1325
1326 // This check fails for example if the lock was busy and
1327 // nodeStateStats couldn't be fetched.
1328 if (stats->fNodeStateStatsAvailable) {
1329 ui->peerServices->setText(
1331 // Sync height is init to -1
1332 if (stats->nodeStateStats.nSyncHeight > -1) {
1333 ui->peerSyncHeight->setText(
1334 QString("%1").arg(stats->nodeStateStats.nSyncHeight));
1335 } else {
1336 ui->peerSyncHeight->setText(tr("Unknown"));
1337 }
1338
1339 // Common height is init to -1
1340 if (stats->nodeStateStats.nCommonHeight > -1) {
1341 ui->peerCommonHeight->setText(
1342 QString("%1").arg(stats->nodeStateStats.nCommonHeight));
1343 } else {
1344 ui->peerCommonHeight->setText(tr("Unknown"));
1345 }
1346
1347 ui->peerHeight->setText(
1348 QString::number(stats->nodeStateStats.m_starting_height));
1349 ui->peerPingWait->setText(
1351 ui->peerRelayTxes->setText(stats->nodeStateStats.m_relay_txs ? "Yes"
1352 : "No");
1353 }
1354
1355 ui->detailWidget->show();
1356}
1357
1359 QWidget::resizeEvent(event);
1360}
1361
1363 QWidget::showEvent(event);
1364
1366 return;
1367 }
1368
1369 // start PeerTableModel auto refresh
1371}
1372
1374 QWidget::hideEvent(event);
1375
1377 return;
1378 }
1379
1380 // stop PeerTableModel auto refresh
1382}
1383
1385 QModelIndex index = ui->peerWidget->indexAt(point);
1386 if (index.isValid()) {
1387 peersTableContextMenu->exec(QCursor::pos());
1388 }
1389}
1390
1392 QModelIndex index = ui->banlistWidget->indexAt(point);
1393 if (index.isValid()) {
1394 banTableContextMenu->exec(QCursor::pos());
1395 }
1396}
1397
1399 // Get selected peer addresses
1400 QList<QModelIndex> nodes =
1402 for (int i = 0; i < nodes.count(); i++) {
1403 // Get currently selected peer address
1404 NodeId id = nodes.at(i).data().toLongLong();
1405 // Find the node, disconnect it and clear the selected node
1406 if (m_node.disconnectById(id)) {
1408 }
1409 }
1410}
1411
1413 if (!clientModel) {
1414 return;
1415 }
1416
1417 // Get selected peer addresses
1418 QList<QModelIndex> nodes =
1420 for (int i = 0; i < nodes.count(); i++) {
1421 // Get currently selected peer address
1422 NodeId id = nodes.at(i).data().toLongLong();
1423
1424 // Get currently selected peer address
1425 int detailNodeRow =
1427 if (detailNodeRow < 0) {
1428 return;
1429 }
1430
1431 // Find possible nodes, ban it and clear the selected node
1432 const CNodeCombinedStats *stats =
1434 if (stats) {
1435 m_node.ban(stats->nodeStats.addr, bantime);
1437 }
1438 }
1441}
1442
1444 if (!clientModel) {
1445 return;
1446 }
1447
1448 // Get selected ban addresses
1449 QList<QModelIndex> nodes =
1451 for (int i = 0; i < nodes.count(); i++) {
1452 // Get currently selected ban address
1453 QString strNode = nodes.at(i).data().toString();
1455
1456 LookupSubNet(strNode.toStdString(), possibleSubnet);
1457 if (possibleSubnet.IsValid() && m_node.unban(possibleSubnet)) {
1459 }
1460 }
1461}
1462
1464 ui->peerWidget->selectionModel()->clearSelection();
1465 cachedNodeids.clear();
1467}
1468
1470 if (!clientModel) {
1471 return;
1472 }
1473
1475 ui->banlistWidget->setVisible(visible);
1476 ui->banHeading->setVisible(visible);
1477}
1478
1480 ui->tabWidget->setCurrentIndex(int(tabType));
1481}
1482
1484 return ui->tabWidget->tabText(int(tab_type));
1485}
1486
1488 switch (tab_type) {
1489 case TabTypes::INFO:
1490 return QKeySequence(Qt::CTRL + Qt::Key_I);
1491 case TabTypes::CONSOLE:
1492 return QKeySequence(Qt::CTRL + Qt::Key_T);
1493 case TabTypes::GRAPH:
1494 return QKeySequence(Qt::CTRL + Qt::Key_N);
1495 case TabTypes::PEERS:
1496 return QKeySequence(Qt::CTRL + Qt::Key_P);
1497 } // no default case, so the compiler can warn about missing cases
1498
1499 assert(false);
1500}
1501
1503 this->ui->label_alerts->setVisible(!warnings.isEmpty());
1504 this->ui->label_alerts->setText(warnings);
1505}
std::string BerkeleyDatabaseVersion()
Definition bdb.cpp:814
const CChainParams & Params()
Return the currently selected parameters.
Model for Bitcoin network client.
Definition clientmodel.h:43
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut)
QString blocksDir() const
QString getStatusBarWarnings() const
Return warnings to be displayed in status bar.
PeerTableModel * getPeerTableModel()
int getNumConnections(NumConnections flags=CONNECTIONS_ALL) const
Return number of connections, default is in- and outbound (total)
void numConnectionsChanged(int count)
QString formatClientStartupTime() const
BanTableModel * getBanTableModel()
void numBlocksChanged(int count, const QDateTime &blockDate, double nVerificationProgress, SyncType header, SynchronizationState sync_state)
void alertsChanged(const QString &warnings)
QString dataDir() const
QString formatFullVersion() const
QString formatSubVersion() const
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes)
void networkActiveChanged(bool networkActive)
interfaces::Node & node() const
Definition clientmodel.h:58
static std::vector< std::string > ToStrings(NetPermissionFlags flags)
const CNodeCombinedStats * getNodeStats(int idx)
int getRowByNodeId(NodeId nodeid)
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
bool getImagesOnButtons() const
QImage SingleColorImage(const QString &filename) const
Colorize an image (given filename) with the icon color.
Class for handling RPC timers (used for e.g.
std::function< void()> func
QtRPCTimerBase(std::function< void()> &_func, int64_t millis)
const char * Name() override
Implementation name.
RPCTimerBase * NewTimer(std::function< void()> &func, int64_t millis) override
Factory function for timers.
Local Bitcoin RPC console.
Definition rpcconsole.h:36
QMenu * peersTableContextMenu
Definition rpcconsole.h:166
RPCConsole(interfaces::Node &node, const PlatformStyle *platformStyle, QWidget *parent)
void cmdRequest(const QString &command, const WalletModel *wallet_model)
void browseHistory(int offset)
Go forward or back in history.
void fontSmaller()
RPCTimerInterface * rpcTimerInterface
Definition rpcconsole.h:165
QString TimeDurationField(std::chrono::seconds time_now, std::chrono::seconds time_at_event) const
Helper for the output of a time duration field.
Definition rpcconsole.h:180
void on_lineEdit_returnPressed()
QStringList history
Definition rpcconsole.h:160
void message(int category, const QString &msg)
Append the message to the message widget.
Definition rpcconsole.h:109
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
Definition rpcconsole.h:164
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)
Definition rpcconsole.h:50
QString tabTitle(TabTypes tab_type) const
void updateNetworkState()
Update UI with latest network info from model.
void disconnectSelectedNode()
Disconnect a selected node on the Peers tab.
@ BANTIME_COLUMN_WIDTH
Definition rpcconsole.h:153
@ ADDRESS_COLUMN_WIDTH
Definition rpcconsole.h:149
@ SUBVERSION_COLUMN_WIDTH
Definition rpcconsole.h:150
@ PING_COLUMN_WIDTH
Definition rpcconsole.h:151
@ BANSUBNET_COLUMN_WIDTH
Definition rpcconsole.h:152
QCompleter * autoCompleter
Definition rpcconsole.h:169
void setMempoolSize(long numberOfTxs, size_t dynUsage)
Set size (number of transactions and memory usage) of the mempool in the UI.
void clear(bool clearHistory=true)
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
Definition rpcconsole.h:163
interfaces::Node & m_node
Definition rpcconsole.h:157
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
int consoleFontSize
Definition rpcconsole.h:168
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
Definition rpcconsole.h:159
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)
Ui::RPCConsole *const ui
Definition rpcconsole.h:158
void startExecutor()
void setNetworkActive(bool networkActive)
Set network state shown in the UI.
void fontBigger()
QString cmdBeforeBrowsing
Definition rpcconsole.h:162
void addWallet(WalletModel *const walletModel)
virtual bool eventFilter(QObject *obj, QEvent *event) override
void on_openDebugLogfileButton_clicked()
open the debug.log from the current datadir
void removeWallet(WalletModel *const walletModel)
void showBanTableContextMenu(const QPoint &point)
Show custom context menu on Bans tab.
void peerLayoutAboutToChange()
Handle selection caching before update.
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)
WalletModel * m_last_wallet_model
Definition rpcconsole.h:171
void showOrHideBanTableIfRequired()
Hides ban table if no bans are present.
QMenu * banTableContextMenu
Definition rpcconsole.h:167
QThread thread
Definition rpcconsole.h:170
void peerLayoutChanged()
Handle updated peer information.
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.
Definition server.h:92
RPC timer "driver".
Definition server.h:100
void push_back(UniValue val)
Definition univalue.cpp:96
Interface to Bitcoin wallet from Qt view code.
Definition walletmodel.h:47
QString getDisplayName() const
static bool isWalletEnabled()
Top-level interface for a bitcoin node (bitcoind process).
Definition node.h:58
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 unban(const CSubNet &ip)=0
Unban node.
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.
Definition client.cpp:272
SyncType
Definition clientmodel.h:40
const Config & GetConfig()
Definition config.cpp:40
QString NetworkToQString(Network net)
Convert enum Network to QString.
Definition guiutil.cpp:789
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition guiutil.cpp:251
QList< QModelIndex > getEntryData(const QAbstractItemView *view, int column)
Return a field of the currently selected entry as a QString.
Definition guiutil.cpp:275
QString formatBytes(uint64_t bytes)
Definition guiutil.cpp:893
QString formatDurationStr(std::chrono::seconds dur)
Convert seconds into a QString with days, hours, mins, secs.
Definition guiutil.cpp:811
void handleCloseWindowShortcut(QWidget *w)
Definition guiutil.cpp:407
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.
Definition guiutil.cpp:851
void openDebugLogfile()
Definition guiutil.cpp:412
QString formatTimeOffset(int64_t nTimeOffset)
Format a CNodeCombinedStats.nTimeOffset into a user-readable string.
Definition guiutil.cpp:859
QString formatServicesStr(quint64 mask)
Format CNodeStats.nServices bitmask into a user-readable string.
Definition guiutil.cpp:835
QFont fixedPitchFont()
Definition guiutil.cpp:87
Definition init.h:28
void ThreadRename(std::string &&)
Rename a thread both in terms of an internal (in-memory) name as well as its system thread name.
bool LookupSubNet(const std::string &strSubnet, CSubNet &ret, DNSLookupFn dns_lookup_function)
Parse and resolve a specified subnet string into the appropriate internal representation.
Definition netbase.cpp:786
NodeContext & m_node
int64_t NodeId
Definition nodeid.h:10
T GetRand(T nMax=std::numeric_limits< T >::max()) noexcept
Generate a uniform random integer of type T in the range [0..nMax) nMax defaults to std::numeric_limi...
Definition random.h:85
const struct @7 ICON_MAPPING[]
const int INITIAL_TRAFFIC_GRAPH_MINS
const QSize FONT_RANGE(4, 40)
const int CONSOLE_HISTORY
static QString categoryClass(int category)
const char fontSizeSettingsKey[]
const char * url
const char * source
int atoi(const std::string &str)
constexpr bool IsDigit(char c)
Tests if the given character is a decimal digit.
CNodeStateStats nodeStateStats
std::chrono::microseconds m_ping_wait
ServiceFlags their_services
std::string addrLocal
Definition net.h:314
uint64_t nRecvBytes
Definition net.h:308
std::chrono::microseconds m_last_ping_time
Definition net.h:311
uint32_t m_mapped_as
Definition net.h:321
bool fInbound
Definition net.h:302
uint64_t nSendBytes
Definition net.h:306
std::chrono::seconds m_last_recv
Definition net.h:293
std::chrono::seconds m_last_send
Definition net.h:292
std::chrono::seconds m_last_tx_time
Definition net.h:294
CAddress addr
Definition net.h:316
std::chrono::microseconds m_min_ping_time
Definition net.h:312
int64_t nTimeOffset
Definition net.h:298
std::chrono::seconds m_connected
Definition net.h:297
bool m_bip152_highbandwidth_from
Definition net.h:304
bool m_bip152_highbandwidth_to
Definition net.h:303
std::string m_addr_name
Definition net.h:299
int nVersion
Definition net.h:300
std::chrono::seconds m_last_block_time
Definition net.h:296
Network m_network
Definition net.h:320
NodeId nodeid
Definition net.h:291
NetPermissionFlags m_permissionFlags
Definition net.h:310
std::string cleanSubVer
Definition net.h:301
static int count
Definition tests.c:31
assert(!tx.IsCoinBase())