Bitcoin ABC  0.24.7
P2P Digital Currency
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 <config.h>
13 #include <interfaces/node.h>
14 #include <netbase.h>
15 #include <qt/bantablemodel.h>
16 #include <qt/clientmodel.h>
17 #include <qt/forms/ui_debugwindow.h>
18 #include <qt/platformstyle.h>
19 #include <qt/walletmodel.h>
20 #include <rpc/client.h>
21 #include <rpc/server.h>
22 #include <util/strencodings.h>
23 #include <util/system.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 
46 const int CONSOLE_HISTORY = 50;
48 const QSize FONT_RANGE(4, 40);
49 const char fontSizeSettingsKey[] = "consoleFontSize";
50 
51 const 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 
60 namespace {
61 
62 // don't add private key handling cmd's to the history
63 const 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  */
75 class RPCExecutor : public QObject {
76  Q_OBJECT
77 public:
78  explicit RPCExecutor(interfaces::Node &node) : m_node(node) {}
79 
80 public Q_SLOTS:
81  void request(const QString &command, const WalletModel *wallet_model);
82 
83 Q_SIGNALS:
84  void reply(int category, const QString &command);
85 
86 private:
88 };
89 
93 class QtRPCTimerBase : public QObject, public RPCTimerBase {
94  Q_OBJECT
95 public:
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 
103 private:
104  QTimer timer;
105  std::function<void()> func;
106 };
107 
109 public:
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 {
156  STATE_EATING_SPACES,
157  STATE_EATING_SPACES_IN_ARG,
158  STATE_EATING_SPACES_IN_BRACKETS,
159  STATE_ARGUMENT,
160  STATE_SINGLEQUOTED,
161  STATE_DOUBLEQUOTED,
162  STATE_ESCAPE_OUTER,
163  STATE_ESCAPE_DOUBLEQUOTED,
164  STATE_COMMAND_EXECUTED,
165  STATE_COMMAND_EXECUTED_INNER
166  } state = STATE_EATING_SPACES;
167  std::string curarg;
168  UniValue lastResult;
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)) {
177  nDepthInsideSensitive = 1;
178  filter_begin_pos = chpos;
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 = [&]() {
188  if (nDepthInsideSensitive) {
189  if (!--nDepthInsideSensitive) {
190  assert(filter_begin_pos);
191  filter_ranges.push_back(
192  std::make_pair(filter_begin_pos, chpos));
193  filter_begin_pos = 0;
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) {
204  char ch = strCommandTerminated[chpos];
205  switch (state) {
206  case STATE_COMMAND_EXECUTED_INNER:
207  case STATE_COMMAND_EXECUTED: {
208  bool breakParsing = true;
209  switch (ch) {
210  case '[':
211  curarg.clear();
212  state = STATE_COMMAND_EXECUTED_INNER;
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
225  UniValue subelement;
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 = find_value(lastResult, curarg);
237  } else {
238  // no array or object: abort
239  throw std::runtime_error(
240  "Invalid result query");
241  }
242  lastResult = subelement;
243  }
244 
245  state = STATE_COMMAND_EXECUTED;
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
254  close_out_params();
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()) {
268  add_to_current_stack(curarg);
269  } else {
270  strResult = curarg;
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
284  case STATE_EATING_SPACES_IN_ARG:
285  case STATE_EATING_SPACES_IN_BRACKETS:
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) {
306  if (nDepthInsideSensitive) {
307  ++nDepthInsideSensitive;
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 
318  add_to_current_stack(curarg);
319  curarg.clear();
320  state = STATE_EATING_SPACES_IN_BRACKETS;
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) {
337  QByteArray encodedName =
338  QUrl::toPercentEncoding(
339  wallet_model->getWalletName());
340  uri = "/wallet/" +
341  std::string(encodedName.constData(),
342  encodedName.length());
343  }
344 #endif
345 
346  GlobalConfig config;
347  assert(node);
348  lastResult = node->executeRpc(config, method,
349  params, uri);
350  }
351 
352  state = STATE_COMMAND_EXECUTED;
353  curarg.clear();
354  }
355  break;
356  case ' ':
357  case ',':
358  case '\t':
359  if (state == STATE_EATING_SPACES_IN_ARG &&
360  curarg.empty() && ch == ',') {
361  throw std::runtime_error("Invalid Syntax");
362  } else if (state == STATE_ARGUMENT) {
363  // Space ends argument
364  add_to_current_stack(curarg);
365  curarg.clear();
366  }
367  if ((state == STATE_EATING_SPACES_IN_BRACKETS ||
368  state == STATE_ARGUMENT) &&
369  ch == ',') {
370  state = STATE_EATING_SPACES_IN_ARG;
371  break;
372  }
373  state = STATE_EATING_SPACES;
374  break;
375  default:
376  curarg += ch;
377  state = STATE_ARGUMENT;
378  }
379  break;
380  case STATE_SINGLEQUOTED: // Single-quoted string
381  switch (ch) {
382  case '\'':
383  state = STATE_ARGUMENT;
384  break;
385  default:
386  curarg += ch;
387  }
388  break;
389  case STATE_DOUBLEQUOTED: // Double-quoted string
390  switch (ch) {
391  case '"':
392  state = STATE_ARGUMENT;
393  break;
394  case '\\':
395  state = STATE_ESCAPE_DOUBLEQUOTED;
396  break;
397  default:
398  curarg += ch;
399  }
400  break;
401  case STATE_ESCAPE_OUTER: // '\' outside quotes
402  curarg += ch;
403  state = STATE_ARGUMENT;
404  break;
405  case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
406  if (ch != '"' && ch != '\\') {
407  // keep '\' for everything but the quote and '\' itself
408  curarg += '\\';
409  }
410  curarg += ch;
411  state = STATE_DOUBLEQUOTED;
412  break;
413  }
414  }
415  if (pstrFilteredOut) {
416  if (STATE_COMMAND_EXECUTED == state) {
417  assert(!stack.empty());
418  close_out_params();
419  }
420  *pstrFilteredOut = strCommand;
421  for (auto i = filter_ranges.rbegin(); i != filter_ranges.rend(); ++i) {
422  pstrFilteredOut->replace(i->first, i->second - i->first, "(…)");
423  }
424  }
425 
426  // final state
427  switch (state) {
428  case STATE_COMMAND_EXECUTED:
429  if (lastResult.isStr()) {
430  strResult = lastResult.get_str();
431  } else {
432  strResult = lastResult.write(2);
433  }
434  // FALLTHROUGH
435  case STATE_ARGUMENT:
436  case STATE_EATING_SPACES:
437  return true;
438  default: // ERROR to end in one of the other states
439  return false;
440  }
441 }
442 
443 void RPCExecutor::request(const QString &command,
444  const WalletModel *wallet_model) {
445  try {
446  std::string result;
447  std::string executableCommand = command.toStdString() + "\n";
448 
449  // Catch the console-only-help command before RPC call is executed and
450  // reply with help text as-if a RPC reply.
451  if (executableCommand == "help-console\n") {
452  Q_EMIT reply(
454  QString(("\n"
455  "This console accepts RPC commands using the standard "
456  "syntax.\n"
457  " example: getblockhash 0\n\n"
458 
459  "This console can also accept RPC commands using "
460  "parenthesized syntax.\n"
461  " example: getblockhash(0)\n\n"
462 
463  "Commands may be nested when specified with the "
464  "parenthesized syntax.\n"
465  " example: getblock(getblockhash(0) 1)\n\n"
466 
467  "A space or a comma can be used to delimit arguments "
468  "for either syntax.\n"
469  " example: getblockhash 0\n"
470  " getblockhash,0\n\n"
471 
472  "Named results can be queried with a non-quoted key "
473  "string in brackets.\n"
474  " example: getblock(getblockhash(0) true)[tx]\n\n"
475 
476  "Results without keys can be queried using an integer "
477  "in brackets.\n"
478  " example: "
479  "getblock(getblockhash(0),true)[tx][0]\n\n")));
480  return;
481  }
483  m_node, result, executableCommand, nullptr, wallet_model)) {
485  QString("Parse error: unbalanced ' or \""));
486  return;
487  }
488 
489  Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(result));
490  } catch (UniValue &objError) {
491  // Nice formatting for standard-format error
492  try {
493  int code = find_value(objError, "code").get_int();
494  std::string message = find_value(objError, "message").get_str();
496  QString::fromStdString(message) + " (code " +
497  QString::number(code) + ")");
498  } catch (const std::runtime_error &) {
499  // raised when converting to invalid type, i.e. missing code or
500  // message. Show raw JSON object.
502  QString::fromStdString(objError.write()));
503  }
504  } catch (const std::exception &e) {
506  QString("Error: ") + QString::fromStdString(e.what()));
507  }
508 }
509 
511  const PlatformStyle *_platformStyle, QWidget *parent)
512  : QWidget(parent), m_node(node), ui(new Ui::RPCConsole),
513  platformStyle(_platformStyle) {
514  ui->setupUi(this);
515  QSettings settings;
516  if (!restoreGeometry(
517  settings.value("RPCConsoleWindowGeometry").toByteArray())) {
518  // Restore failed (perhaps missing setting), center the window
519  move(QGuiApplication::primaryScreen()->availableGeometry().center() -
520  frameGeometry().center());
521  }
522 
523  QChar nonbreaking_hyphen(8209);
524  ui->dataDir->setToolTip(
525  ui->dataDir->toolTip().arg(QString(nonbreaking_hyphen) + "datadir"));
526  ui->blocksDir->setToolTip(ui->blocksDir->toolTip().arg(
527  QString(nonbreaking_hyphen) + "blocksdir"));
528  ui->openDebugLogfileButton->setToolTip(
529  ui->openDebugLogfileButton->toolTip().arg(PACKAGE_NAME));
530 
532  ui->openDebugLogfileButton->setIcon(
533  platformStyle->SingleColorIcon(":/icons/export"));
534  }
535  ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
536  ui->fontBiggerButton->setIcon(
537  platformStyle->SingleColorIcon(":/icons/fontbigger"));
538  ui->fontSmallerButton->setIcon(
539  platformStyle->SingleColorIcon(":/icons/fontsmaller"));
540 
541  // Install event filter for up and down arrow
542  ui->lineEdit->installEventFilter(this);
543  ui->lineEdit->setMaxLength(16 * 1024 * 1024);
544  ui->messagesWidget->installEventFilter(this);
545 
546  connect(ui->clearButton, &QPushButton::clicked, this, &RPCConsole::clear);
547  connect(ui->fontBiggerButton, &QPushButton::clicked, this,
549  connect(ui->fontSmallerButton, &QPushButton::clicked, this,
551  connect(ui->btnClearTrafficGraph, &QPushButton::clicked, ui->trafficGraph,
553 
554  // disable the wallet selector by default
555  ui->WalletSelector->setVisible(false);
556  ui->WalletSelectorLabel->setVisible(false);
557 
558 // set library version labels
559 #ifdef ENABLE_WALLET
560  ui->berkeleyDBVersion->setText(
561  QString::fromStdString(BerkeleyDatabaseVersion()));
562 #else
563  ui->label_berkeleyDBVersion->hide();
564  ui->berkeleyDBVersion->hide();
565 #endif
566  // Register RPC timer interface
568  // avoid accidentally overwriting an existing, non QTThread
569  // based timer interface
571 
573 
574  ui->detailWidget->hide();
575  ui->peerHeading->setText(tr("Select a peer to view detailed information."));
576 
578  settings.value(fontSizeSettingsKey, QFont().pointSize()).toInt();
579  clear();
580 
582 }
583 
585  QSettings settings;
586  settings.setValue("RPCConsoleWindowGeometry", saveGeometry());
588  delete rpcTimerInterface;
589  delete ui;
590 }
591 
592 bool RPCConsole::eventFilter(QObject *obj, QEvent *event) {
593  // Special key handling
594  if (event->type() == QEvent::KeyPress) {
595  QKeyEvent *keyevt = static_cast<QKeyEvent *>(event);
596  int key = keyevt->key();
597  Qt::KeyboardModifiers mod = keyevt->modifiers();
598  switch (key) {
599  case Qt::Key_Up:
600  if (obj == ui->lineEdit) {
601  browseHistory(-1);
602  return true;
603  }
604  break;
605  case Qt::Key_Down:
606  if (obj == ui->lineEdit) {
607  browseHistory(1);
608  return true;
609  }
610  break;
611  case Qt::Key_PageUp: /* pass paging keys to messages widget */
612  case Qt::Key_PageDown:
613  if (obj == ui->lineEdit) {
614  QApplication::postEvent(ui->messagesWidget,
615  new QKeyEvent(*keyevt));
616  return true;
617  }
618  break;
619  case Qt::Key_Return:
620  case Qt::Key_Enter:
621  // forward these events to lineEdit
622  if (obj == autoCompleter->popup()) {
623  QApplication::postEvent(ui->lineEdit,
624  new QKeyEvent(*keyevt));
625  return true;
626  }
627  break;
628  default:
629  // Typing in messages widget brings focus to line edit, and
630  // redirects key there. Exclude most combinations and keys that
631  // emit no text, except paste shortcuts.
632  if (obj == ui->messagesWidget &&
633  ((!mod && !keyevt->text().isEmpty() &&
634  key != Qt::Key_Tab) ||
635  ((mod & Qt::ControlModifier) && key == Qt::Key_V) ||
636  ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert))) {
637  ui->lineEdit->setFocus();
638  QApplication::postEvent(ui->lineEdit,
639  new QKeyEvent(*keyevt));
640  return true;
641  }
642  }
643  }
644  return QWidget::eventFilter(obj, event);
645 }
646 
647 void RPCConsole::setClientModel(ClientModel *model, int bestblock_height,
648  int64_t bestblock_date,
649  double verification_progress) {
650  clientModel = model;
651 
652  bool wallet_enabled{false};
653 #ifdef ENABLE_WALLET
654  wallet_enabled = WalletModel::isWalletEnabled();
655 #endif // ENABLE_WALLET
656  if (model && !wallet_enabled) {
657  // Show warning, for example if this is a prerelease version
658  connect(model, &ClientModel::alertsChanged, this,
661  }
662 
663  ui->trafficGraph->setClientModel(model);
664  if (model && clientModel->getPeerTableModel() &&
666  // Keep up to date with client
668  connect(model, &ClientModel::numConnectionsChanged, this,
670 
671  setNumBlocks(bestblock_height, QDateTime::fromTime_t(bestblock_date),
672  verification_progress, false);
673  connect(model, &ClientModel::numBlocksChanged, this,
675 
677  connect(model, &ClientModel::networkActiveChanged, this,
679 
680  interfaces::Node &node = clientModel->node();
682  connect(model, &ClientModel::bytesChanged, this,
684 
685  connect(model, &ClientModel::mempoolSizeChanged, this,
687 
688  // set up peer table
689  ui->peerWidget->setModel(model->getPeerTableModel());
690  ui->peerWidget->verticalHeader()->hide();
691  ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
692  ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
693  ui->peerWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
694  ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu);
695  ui->peerWidget->setColumnWidth(PeerTableModel::Address,
697  ui->peerWidget->setColumnWidth(PeerTableModel::Subversion,
699  ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH);
700  ui->peerWidget->horizontalHeader()->setStretchLastSection(true);
701 
702  // create peer table context menu actions
703  QAction *disconnectAction = new QAction(tr("&Disconnect"), this);
704  QAction *banAction1h =
705  new QAction(tr("Ban for") + " " + tr("1 &hour"), this);
706  QAction *banAction24h =
707  new QAction(tr("Ban for") + " " + tr("1 &day"), this);
708  QAction *banAction7d =
709  new QAction(tr("Ban for") + " " + tr("1 &week"), this);
710  QAction *banAction365d =
711  new QAction(tr("Ban for") + " " + tr("1 &year"), this);
712 
713  // create peer table context menu
714  peersTableContextMenu = new QMenu(this);
715  peersTableContextMenu->addAction(disconnectAction);
716  peersTableContextMenu->addAction(banAction1h);
717  peersTableContextMenu->addAction(banAction24h);
718  peersTableContextMenu->addAction(banAction7d);
719  peersTableContextMenu->addAction(banAction365d);
720 
721  connect(banAction1h, &QAction::triggered,
722  [this] { banSelectedNode(60 * 60); });
723  connect(banAction24h, &QAction::triggered,
724  [this] { banSelectedNode(60 * 60 * 24); });
725  connect(banAction7d, &QAction::triggered,
726  [this] { banSelectedNode(60 * 60 * 24 * 7); });
727  connect(banAction365d, &QAction::triggered,
728  [this] { banSelectedNode(60 * 60 * 24 * 365); });
729 
730  // peer table context menu signals
731  connect(ui->peerWidget, &QTableView::customContextMenuRequested, this,
733  connect(disconnectAction, &QAction::triggered, this,
735 
736  // peer table signal handling - update peer details when selecting new
737  // node
738  connect(ui->peerWidget->selectionModel(),
739  &QItemSelectionModel::selectionChanged, this,
741  // peer table signal handling - update peer details when new nodes are
742  // added to the model
743  connect(model->getPeerTableModel(), &PeerTableModel::layoutChanged,
745  // peer table signal handling - cache selected node ids
746  connect(model->getPeerTableModel(),
747  &PeerTableModel::layoutAboutToBeChanged, this,
749 
750  // set up ban table
751  ui->banlistWidget->setModel(model->getBanTableModel());
752  ui->banlistWidget->verticalHeader()->hide();
753  ui->banlistWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
754  ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
755  ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection);
756  ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu);
757  ui->banlistWidget->setColumnWidth(BanTableModel::Address,
759  ui->banlistWidget->setColumnWidth(BanTableModel::Bantime,
761  ui->banlistWidget->horizontalHeader()->setStretchLastSection(true);
762 
763  // create ban table context menu action
764  QAction *unbanAction = new QAction(tr("&Unban"), this);
765 
766  // create ban table context menu
767  banTableContextMenu = new QMenu(this);
768  banTableContextMenu->addAction(unbanAction);
769 
770  // ban table context menu signals
771  connect(ui->banlistWidget, &QTableView::customContextMenuRequested,
773  connect(unbanAction, &QAction::triggered, this,
775 
776  // ban table signal handling - clear peer details when clicking a peer
777  // in the ban table
778  connect(ui->banlistWidget, &QTableView::clicked, this,
780  // ban table signal handling - ensure ban table is shown or hidden (if
781  // empty)
782  connect(model->getBanTableModel(), &BanTableModel::layoutChanged, this,
785 
786  // Provide initial values
787  ui->clientVersion->setText(model->formatFullVersion());
788  ui->clientUserAgent->setText(model->formatSubVersion());
789  ui->dataDir->setText(model->dataDir());
790  ui->blocksDir->setText(model->blocksDir());
791  ui->startupTime->setText(model->formatClientStartupTime());
792  ui->networkName->setText(
793  QString::fromStdString(Params().NetworkIDString()));
794 
795  // Setup autocomplete and attach it
796  QStringList wordList;
797  std::vector<std::string> commandList = m_node.listRpcCommands();
798  for (size_t i = 0; i < commandList.size(); ++i) {
799  wordList << commandList[i].c_str();
800  wordList << ("help " + commandList[i]).c_str();
801  }
802 
803  wordList << "help-console";
804  wordList.sort();
805  autoCompleter = new QCompleter(wordList, this);
806  autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel);
807  // ui->lineEdit is initially disabled because running commands is only
808  // possible from now on.
809  ui->lineEdit->setEnabled(true);
810  ui->lineEdit->setCompleter(autoCompleter);
811  autoCompleter->popup()->installEventFilter(this);
812  // Start thread to execute RPC commands.
813  startExecutor();
814  }
815  if (!model) {
816  // Client model is being set to 0, this means shutdown() is about to be
817  // called.
818  thread.quit();
819  thread.wait();
820  }
821 }
822 
823 #ifdef ENABLE_WALLET
824 void RPCConsole::addWallet(WalletModel *const walletModel) {
825  // use name for text and wallet model for internal data object (to allow to
826  // move to a wallet id later)
827  ui->WalletSelector->addItem(walletModel->getDisplayName(),
828  QVariant::fromValue(walletModel));
829  if (ui->WalletSelector->count() == 2 && !isVisible()) {
830  // First wallet added, set to default so long as the window isn't
831  // presently visible (and potentially in use)
832  ui->WalletSelector->setCurrentIndex(1);
833  }
834  if (ui->WalletSelector->count() > 2) {
835  ui->WalletSelector->setVisible(true);
836  ui->WalletSelectorLabel->setVisible(true);
837  }
838 }
839 
840 void RPCConsole::removeWallet(WalletModel *const walletModel) {
841  ui->WalletSelector->removeItem(
842  ui->WalletSelector->findData(QVariant::fromValue(walletModel)));
843  if (ui->WalletSelector->count() == 2) {
844  ui->WalletSelector->setVisible(false);
845  ui->WalletSelectorLabel->setVisible(false);
846  }
847 }
848 #endif
849 
850 static QString categoryClass(int category) {
851  switch (category) {
853  return "cmd-request";
854  break;
856  return "cmd-reply";
857  break;
859  return "cmd-error";
860  break;
861  default:
862  return "misc";
863  }
864 }
865 
868 }
869 
872 }
873 
874 void RPCConsole::setFontSize(int newSize) {
875  QSettings settings;
876 
877  // don't allow an insane font size
878  if (newSize < FONT_RANGE.width() || newSize > FONT_RANGE.height()) {
879  return;
880  }
881 
882  // temp. store the console content
883  QString str = ui->messagesWidget->toHtml();
884 
885  // replace font tags size in current content
886  str.replace(QString("font-size:%1pt").arg(consoleFontSize),
887  QString("font-size:%1pt").arg(newSize));
888 
889  // store the new font size
890  consoleFontSize = newSize;
891  settings.setValue(fontSizeSettingsKey, consoleFontSize);
892 
893  // clear console (reset icon sizes, default stylesheet) and re-add the
894  // content
895  float oldPosFactor = 1.0 /
896  ui->messagesWidget->verticalScrollBar()->maximum() *
897  ui->messagesWidget->verticalScrollBar()->value();
898  clear(false);
899  ui->messagesWidget->setHtml(str);
900  ui->messagesWidget->verticalScrollBar()->setValue(
901  oldPosFactor * ui->messagesWidget->verticalScrollBar()->maximum());
902 }
903 
904 void RPCConsole::clear(bool clearHistory) {
905  ui->messagesWidget->clear();
906  if (clearHistory) {
907  history.clear();
908  historyPtr = 0;
909  }
910  ui->lineEdit->clear();
911  ui->lineEdit->setFocus();
912 
913  // Add smoothly scaled icon images.
914  // (when using width/height on an img, Qt uses nearest instead of linear
915  // interpolation)
916  for (int i = 0; ICON_MAPPING[i].url; ++i) {
917  ui->messagesWidget->document()->addResource(
918  QTextDocument::ImageResource, QUrl(ICON_MAPPING[i].url),
920  .scaled(QSize(consoleFontSize * 2, consoleFontSize * 2),
921  Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
922  }
923 
924  // Set default style sheet
925  QFontInfo fixedFontInfo(GUIUtil::fixedPitchFont());
926  ui->messagesWidget->document()->setDefaultStyleSheet(
927  QString("table { }"
928  "td.time { color: #808080; font-size: %2; padding-top: 3px; } "
929  "td.message { font-family: %1; font-size: %2; "
930  "white-space:pre-wrap; } "
931  "td.cmd-request { color: #006060; } "
932  "td.cmd-error { color: red; } "
933  ".secwarning { color: red; }"
934  "b { color: #006060; } ")
935  .arg(fixedFontInfo.family(), QString("%1pt").arg(consoleFontSize)));
936 
937 #ifdef Q_OS_MAC
938  QString clsKey = "(⌘)-L";
939 #else
940  QString clsKey = "Ctrl-L";
941 #endif
942 
944  (tr("Welcome to the %1 RPC console.").arg(PACKAGE_NAME) + "<br>" +
945  tr("Use up and down arrows to navigate history, and "
946  "%1 to clear screen.")
947  .arg("<b>" + clsKey + "</b>") +
948  "<br>" +
949  tr("Type %1 for an overview of available commands.")
950  .arg("<b>help</b>") +
951  "<br>" +
952  tr("For more information on using this console type %1.")
953  .arg("<b>help-console</b>") +
954  "<br><span class=\"secwarning\"><br>" +
955  tr("WARNING: Scammers have been active, telling users to type "
956  "commands here, stealing their wallet contents. Do not use "
957  "this console without fully understanding the ramifications "
958  "of a command.") +
959  "</span>"),
960  true);
961 }
962 
963 void RPCConsole::keyPressEvent(QKeyEvent *event) {
964  if (windowType() != Qt::Widget && event->key() == Qt::Key_Escape) {
965  close();
966  }
967 }
968 
969 void RPCConsole::message(int category, const QString &message, bool html) {
970  QTime time = QTime::currentTime();
971  QString timeString = time.toString();
972  QString out;
973  out += "<table><tr><td class=\"time\" width=\"65\">" + timeString + "</td>";
974  out += "<td class=\"icon\" width=\"32\"><img src=\"" +
975  categoryClass(category) + "\"></td>";
976  out += "<td class=\"message " + categoryClass(category) +
977  "\" valign=\"middle\">";
978  if (html) {
979  out += message;
980  } else {
981  out += GUIUtil::HtmlEscape(message, false);
982  }
983  out += "</td></tr></table>";
984  ui->messagesWidget->append(out);
985 }
986 
988  QString connections =
989  QString::number(clientModel->getNumConnections()) + " (";
990  connections += tr("In:") + " " +
991  QString::number(clientModel->getNumConnections(
993  " / ";
994  connections += tr("Out:") + " " +
995  QString::number(clientModel->getNumConnections(
997  ")";
998 
999  if (!clientModel->node().getNetworkActive()) {
1000  connections += " (" + tr("Network activity disabled") + ")";
1001  }
1002 
1003  ui->numberOfConnections->setText(connections);
1004 }
1005 
1007  if (!clientModel) {
1008  return;
1009  }
1010 
1012 }
1013 
1014 void RPCConsole::setNetworkActive(bool networkActive) {
1016 }
1017 
1018 void RPCConsole::setNumBlocks(int count, const QDateTime &blockDate,
1019  double nVerificationProgress, bool headers) {
1020  if (!headers) {
1021  ui->numberOfBlocks->setText(QString::number(count));
1022  ui->lastBlockTime->setText(blockDate.toString());
1023  }
1024 }
1025 
1026 void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage) {
1027  ui->mempoolNumberTxs->setText(QString::number(numberOfTxs));
1028 
1029  if (dynUsage < 1000000) {
1030  ui->mempoolSize->setText(QString::number(dynUsage / 1000.0, 'f', 2) +
1031  " KB");
1032  } else {
1033  ui->mempoolSize->setText(QString::number(dynUsage / 1000000.0, 'f', 2) +
1034  " MB");
1035  }
1036 }
1037 
1039  QString cmd = ui->lineEdit->text();
1040 
1041  if (!cmd.isEmpty()) {
1042  std::string strFilteredCmd;
1043  try {
1044  std::string dummy;
1045  if (!RPCParseCommandLine(nullptr, dummy, cmd.toStdString(), false,
1046  &strFilteredCmd)) {
1047  // Failed to parse command, so we cannot even filter it for the
1048  // history
1049  throw std::runtime_error("Invalid command line");
1050  }
1051  } catch (const std::exception &e) {
1052  QMessageBox::critical(this, "Error",
1053  QString("Error: ") +
1054  QString::fromStdString(e.what()));
1055  return;
1056  }
1057 
1058  ui->lineEdit->clear();
1059 
1060  cmdBeforeBrowsing = QString();
1061 
1062 #ifdef ENABLE_WALLET
1063  WalletModel *wallet_model =
1064  ui->WalletSelector->currentData().value<WalletModel *>();
1065 
1066  if (m_last_wallet_model != wallet_model) {
1067  if (wallet_model) {
1068  message(CMD_REQUEST, tr("Executing command using \"%1\" wallet")
1069  .arg(wallet_model->getWalletName()));
1070  } else {
1072  tr("Executing command without any wallet"));
1073  }
1074  m_last_wallet_model = wallet_model;
1075  }
1076 #endif
1077 
1078  message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
1079  Q_EMIT cmdRequest(cmd, m_last_wallet_model);
1080 
1081  cmd = QString::fromStdString(strFilteredCmd);
1082 
1083  // Remove command, if already in history
1084  history.removeOne(cmd);
1085  // Append command to history
1086  history.append(cmd);
1087  // Enforce maximum history size
1088  while (history.size() > CONSOLE_HISTORY) {
1089  history.removeFirst();
1090  }
1091  // Set pointer to end of history
1092  historyPtr = history.size();
1093 
1094  // Scroll console view to end
1095  scrollToEnd();
1096  }
1097 }
1098 
1099 void RPCConsole::browseHistory(int offset) {
1100  // store current text when start browsing through the history
1101  if (historyPtr == history.size()) {
1102  cmdBeforeBrowsing = ui->lineEdit->text();
1103  }
1104 
1105  historyPtr += offset;
1106  if (historyPtr < 0) {
1107  historyPtr = 0;
1108  }
1109  if (historyPtr > history.size()) {
1110  historyPtr = history.size();
1111  }
1112  QString cmd;
1113  if (historyPtr < history.size()) {
1114  cmd = history.at(historyPtr);
1115  } else if (!cmdBeforeBrowsing.isNull()) {
1116  cmd = cmdBeforeBrowsing;
1117  }
1118  ui->lineEdit->setText(cmd);
1119 }
1120 
1122  RPCExecutor *executor = new RPCExecutor(m_node);
1123  executor->moveToThread(&thread);
1124 
1125  // Replies from executor object must go to this object
1126  connect(executor, &RPCExecutor::reply, this,
1127  static_cast<void (RPCConsole::*)(int, const QString &)>(
1129 
1130  // Requests from this object must go to executor
1131  connect(this, &RPCConsole::cmdRequest, executor, &RPCExecutor::request);
1132 
1133  // Make sure executor object is deleted in its own thread
1134  connect(&thread, &QThread::finished, executor, &RPCExecutor::deleteLater);
1135 
1136  // Default implementation of QThread::run() simply spins up an event loop in
1137  // the thread, which is what we want.
1138  thread.start();
1139  QTimer::singleShot(0, executor,
1140  []() { util::ThreadRename("qt-rpcconsole"); });
1141 }
1142 
1144  if (ui->tabWidget->widget(index) == ui->tab_console) {
1145  ui->lineEdit->setFocus();
1146  }
1147 }
1148 
1151 }
1152 
1154  QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
1155  scrollbar->setValue(scrollbar->maximum());
1156 }
1157 
1159  const int multiplier = 5; // each position on the slider represents 5 min
1160  int mins = value * multiplier;
1161  setTrafficGraphRange(mins);
1162 }
1163 
1165  ui->trafficGraph->setGraphRangeMins(mins);
1166  ui->lblGraphRange->setText(GUIUtil::formatDurationStr(mins * 60));
1167 }
1168 
1169 void RPCConsole::updateTrafficStats(quint64 totalBytesIn,
1170  quint64 totalBytesOut) {
1171  ui->lblBytesIn->setText(GUIUtil::formatBytes(totalBytesIn));
1172  ui->lblBytesOut->setText(GUIUtil::formatBytes(totalBytesOut));
1173 }
1174 
1175 void RPCConsole::peerSelected(const QItemSelection &selected,
1176  const QItemSelection &deselected) {
1177  Q_UNUSED(deselected);
1178 
1180  selected.indexes().isEmpty()) {
1181  return;
1182  }
1183 
1184  const CNodeCombinedStats *stats =
1186  selected.indexes().first().row());
1187  if (stats) {
1188  updateNodeDetail(stats);
1189  }
1190 }
1191 
1193  QModelIndexList selected =
1194  ui->peerWidget->selectionModel()->selectedIndexes();
1195  cachedNodeids.clear();
1196  for (int i = 0; i < selected.size(); i++) {
1197  const CNodeCombinedStats *stats =
1199  selected.at(i).row());
1200  cachedNodeids.append(stats->nodeStats.nodeid);
1201  }
1202 }
1203 
1206  return;
1207  }
1208 
1209  const CNodeCombinedStats *stats = nullptr;
1210  bool fUnselect = false;
1211  bool fReselect = false;
1212 
1213  // no node selected yet
1214  if (cachedNodeids.empty()) {
1215  return;
1216  }
1217 
1218  // find the currently selected row
1219  int selectedRow = -1;
1220  QModelIndexList selectedModelIndex =
1221  ui->peerWidget->selectionModel()->selectedIndexes();
1222  if (!selectedModelIndex.isEmpty()) {
1223  selectedRow = selectedModelIndex.first().row();
1224  }
1225 
1226  // check if our detail node has a row in the table (it may not necessarily
1227  // be at selectedRow since its position can change after a layout change)
1228  int detailNodeRow =
1230 
1231  if (detailNodeRow < 0) {
1232  // detail node disappeared from table (node disconnected)
1233  fUnselect = true;
1234  } else {
1235  if (detailNodeRow != selectedRow) {
1236  // detail node moved position
1237  fUnselect = true;
1238  fReselect = true;
1239  }
1240 
1241  // get fresh stats on the detail node.
1242  stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
1243  }
1244 
1245  if (fUnselect && selectedRow >= 0) {
1247  }
1248 
1249  if (fReselect) {
1250  for (int i = 0; i < cachedNodeids.size(); i++) {
1251  ui->peerWidget->selectRow(
1253  cachedNodeids.at(i)));
1254  }
1255  }
1256 
1257  if (stats) {
1258  updateNodeDetail(stats);
1259  }
1260 }
1261 
1263  // update the detail ui with latest node information
1264  QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName) +
1265  " ");
1266  peerAddrDetails +=
1267  tr("(node id: %1)").arg(QString::number(stats->nodeStats.nodeid));
1268  if (!stats->nodeStats.addrLocal.empty()) {
1269  peerAddrDetails += "<br />" + tr("via %1").arg(QString::fromStdString(
1270  stats->nodeStats.addrLocal));
1271  }
1272  ui->peerHeading->setText(peerAddrDetails);
1273  ui->peerServices->setText(
1275  ui->peerLastSend->setText(
1276  stats->nodeStats.nLastSend
1278  stats->nodeStats.nLastSend)
1279  : tr("never"));
1280  ui->peerLastRecv->setText(
1281  stats->nodeStats.nLastRecv
1283  stats->nodeStats.nLastRecv)
1284  : tr("never"));
1285  ui->peerBytesSent->setText(
1287  ui->peerBytesRecv->setText(
1289  ui->peerConnTime->setText(GUIUtil::formatDurationStr(
1291  ui->peerPingTime->setText(
1293  ui->peerPingWait->setText(
1295  ui->peerMinPing->setText(
1297  ui->timeoffset->setText(
1299  ui->peerVersion->setText(QString::number(stats->nodeStats.nVersion));
1300  ui->peerSubversion->setText(
1301  QString::fromStdString(stats->nodeStats.cleanSubVer));
1302  ui->peerDirection->setText(stats->nodeStats.fInbound ? tr("Inbound")
1303  : tr("Outbound"));
1304  ui->peerHeight->setText(QString::number(stats->nodeStats.nStartingHeight));
1305  if (stats->nodeStats.m_permissionFlags == PF_NONE) {
1306  ui->peerPermissions->setText(tr("N/A"));
1307  } else {
1308  QStringList permissions;
1309  for (const auto &permission :
1311  permissions.append(QString::fromStdString(permission));
1312  }
1313  ui->peerPermissions->setText(permissions.join(" & "));
1314  }
1315  ui->peerMappedAS->setText(
1316  stats->nodeStats.m_mapped_as != 0
1317  ? QString::number(stats->nodeStats.m_mapped_as)
1318  : tr("N/A"));
1319 
1320  // This check fails for example if the lock was busy and
1321  // nodeStateStats couldn't be fetched.
1322  if (stats->fNodeStateStatsAvailable) {
1323  // Sync height is init to -1
1324  if (stats->nodeStateStats.nSyncHeight > -1) {
1325  ui->peerSyncHeight->setText(
1326  QString("%1").arg(stats->nodeStateStats.nSyncHeight));
1327  } else {
1328  ui->peerSyncHeight->setText(tr("Unknown"));
1329  }
1330 
1331  // Common height is init to -1
1332  if (stats->nodeStateStats.nCommonHeight > -1) {
1333  ui->peerCommonHeight->setText(
1334  QString("%1").arg(stats->nodeStateStats.nCommonHeight));
1335  } else {
1336  ui->peerCommonHeight->setText(tr("Unknown"));
1337  }
1338  }
1339 
1340  ui->detailWidget->show();
1341 }
1342 
1343 void RPCConsole::resizeEvent(QResizeEvent *event) {
1344  QWidget::resizeEvent(event);
1345 }
1346 
1347 void RPCConsole::showEvent(QShowEvent *event) {
1348  QWidget::showEvent(event);
1349 
1351  return;
1352  }
1353 
1354  // start PeerTableModel auto refresh
1356 }
1357 
1358 void RPCConsole::hideEvent(QHideEvent *event) {
1359  QWidget::hideEvent(event);
1360 
1362  return;
1363  }
1364 
1365  // stop PeerTableModel auto refresh
1367 }
1368 
1369 void RPCConsole::showPeersTableContextMenu(const QPoint &point) {
1370  QModelIndex index = ui->peerWidget->indexAt(point);
1371  if (index.isValid()) {
1372  peersTableContextMenu->exec(QCursor::pos());
1373  }
1374 }
1375 
1376 void RPCConsole::showBanTableContextMenu(const QPoint &point) {
1377  QModelIndex index = ui->banlistWidget->indexAt(point);
1378  if (index.isValid()) {
1379  banTableContextMenu->exec(QCursor::pos());
1380  }
1381 }
1382 
1384  // Get selected peer addresses
1385  QList<QModelIndex> nodes =
1387  for (int i = 0; i < nodes.count(); i++) {
1388  // Get currently selected peer address
1389  NodeId id = nodes.at(i).data().toLongLong();
1390  // Find the node, disconnect it and clear the selected node
1391  if (m_node.disconnectById(id)) {
1393  }
1394  }
1395 }
1396 
1397 void RPCConsole::banSelectedNode(int bantime) {
1398  if (!clientModel) {
1399  return;
1400  }
1401 
1402  // Get selected peer addresses
1403  QList<QModelIndex> nodes =
1405  for (int i = 0; i < nodes.count(); i++) {
1406  // Get currently selected peer address
1407  NodeId id = nodes.at(i).data().toLongLong();
1408 
1409  // Get currently selected peer address
1410  int detailNodeRow =
1412  if (detailNodeRow < 0) {
1413  return;
1414  }
1415 
1416  // Find possible nodes, ban it and clear the selected node
1417  const CNodeCombinedStats *stats =
1418  clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
1419  if (stats) {
1420  m_node.ban(stats->nodeStats.addr, bantime);
1422  }
1423  }
1426 }
1427 
1429  if (!clientModel) {
1430  return;
1431  }
1432 
1433  // Get selected ban addresses
1434  QList<QModelIndex> nodes =
1436  for (int i = 0; i < nodes.count(); i++) {
1437  // Get currently selected ban address
1438  QString strNode = nodes.at(i).data().toString();
1439  CSubNet possibleSubnet;
1440 
1441  LookupSubNet(strNode.toStdString(), possibleSubnet);
1442  if (possibleSubnet.IsValid() && m_node.unban(possibleSubnet)) {
1444  }
1445  }
1446 }
1447 
1449  ui->peerWidget->selectionModel()->clearSelection();
1450  cachedNodeids.clear();
1451  ui->detailWidget->hide();
1452  ui->peerHeading->setText(tr("Select a peer to view detailed information."));
1453 }
1454 
1456  if (!clientModel) {
1457  return;
1458  }
1459 
1460  bool visible = clientModel->getBanTableModel()->shouldShow();
1461  ui->banlistWidget->setVisible(visible);
1462  ui->banHeading->setVisible(visible);
1463 }
1464 
1465 void RPCConsole::setTabFocus(enum TabTypes tabType) {
1466  ui->tabWidget->setCurrentIndex(int(tabType));
1467 }
1468 
1469 QString RPCConsole::tabTitle(TabTypes tab_type) const {
1470  return ui->tabWidget->tabText(int(tab_type));
1471 }
1472 
1473 QKeySequence RPCConsole::tabShortcut(TabTypes tab_type) const {
1474  switch (tab_type) {
1475  case TabTypes::INFO:
1476  return QKeySequence(Qt::CTRL + Qt::Key_I);
1477  case TabTypes::CONSOLE:
1478  return QKeySequence(Qt::CTRL + Qt::Key_T);
1479  case TabTypes::GRAPH:
1480  return QKeySequence(Qt::CTRL + Qt::Key_N);
1481  case TabTypes::PEERS:
1482  return QKeySequence(Qt::CTRL + Qt::Key_P);
1483  } // no default case, so the compiler can warn about missing cases
1484 
1485  assert(false);
1486 }
1487 
1488 void RPCConsole::updateAlerts(const QString &warnings) {
1489  this->ui->label_alerts->setVisible(!warnings.isEmpty());
1490  this->ui->label_alerts->setText(warnings);
1491 }
interfaces::Node::ban
virtual bool ban(const CNetAddr &net_addr, int64_t ban_time_offset)=0
Ban node.
ICON_MAPPING
const struct @7 ICON_MAPPING[]
RPCConsole::TabTypes::CONSOLE
@ CONSOLE
ClientModel::alertsChanged
void alertsChanged(const QString &warnings)
RPCExecutor::RPCExecutor
RPCExecutor(interfaces::Node &node)
Definition: rpcconsole.cpp:78
ClientModel::numBlocksChanged
void numBlocksChanged(int count, const QDateTime &blockDate, double nVerificationProgress, bool header, SynchronizationState sync_state)
CNodeStats::nLastSend
int64_t nLastSend
Definition: net.h:761
CNodeStateStats::nCommonHeight
int nCommonHeight
Definition: net_processing.h:241
RPCConsole::setNumConnections
void setNumConnections(int count)
Set number of connections shown in the UI.
Definition: rpcconsole.cpp:1006
count
static int count
Definition: tests.c:41
ClientModel::numConnectionsChanged
void numConnectionsChanged(int count)
RPCConsole::ADDRESS_COLUMN_WIDTH
@ ADDRESS_COLUMN_WIDTH
Definition: rpcconsole.h:152
fontSizeSettingsKey
const char fontSizeSettingsKey[]
Definition: rpcconsole.cpp:49
ClientModel::mempoolSizeChanged
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes)
PeerTableModel::NetNodeId
@ NetNodeId
Definition: peertablemodel.h:60
wallet.h
CNodeStats::nTimeOffset
int64_t nTimeOffset
Definition: net.h:767
NetPermissions::ToStrings
static std::vector< std::string > ToStrings(NetPermissionFlags flags)
Definition: net_permissions.cpp:97
interfaces::Node::getNetworkActive
virtual bool getNetworkActive()=0
Get network active.
WalletModel
Interface to Bitcoin wallet from Qt view code.
Definition: walletmodel.h:47
QtRPCTimerBase
Class for handling RPC timers (used for e.g.
Definition: rpcconsole.cpp:93
ClientModel::CONNECTIONS_IN
@ CONNECTIONS_IN
Definition: clientmodel.h:42
UniValue::clear
void clear()
Definition: univalue.cpp:15
CNodeCombinedStats::nodeStats
CNodeStats nodeStats
Definition: peertablemodel.h:27
RPCConsole::startExecutor
void startExecutor()
Definition: rpcconsole.cpp:1121
RPCTimerInterface
RPC timer "driver".
Definition: server.h:100
PlatformStyle::SingleColorIcon
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
Definition: platformstyle.cpp:97
PF_NONE
@ PF_NONE
Definition: net_permissions.h:18
interfaces::Node::disconnectById
virtual bool disconnectById(NodeId id)=0
Disconnect node by id.
CNodeStats::m_min_ping_usec
int64_t m_min_ping_usec
Definition: net.h:782
walletmodel.h
RPCConsole::resizeEvent
void resizeEvent(QResizeEvent *event) override
Definition: rpcconsole.cpp:1343
RPCConsole::clearSelectedNode
void clearSelectedNode()
clear the selected node
Definition: rpcconsole.cpp:1448
INITIAL_TRAFFIC_GRAPH_MINS
const int INITIAL_TRAFFIC_GRAPH_MINS
Definition: rpcconsole.cpp:47
atoi
int atoi(const std::string &str)
Definition: strencodings.cpp:477
CNodeStats::nodeid
NodeId nodeid
Definition: net.h:758
source
const char * source
Definition: rpcconsole.cpp:53
WalletModel::isWalletEnabled
static bool isWalletEnabled()
Definition: walletmodel.cpp:514
RPCConsole::keyPressEvent
void keyPressEvent(QKeyEvent *) override
Definition: rpcconsole.cpp:963
RPCConsole::platformStyle
const PlatformStyle *const platformStyle
Definition: rpcconsole.h:167
ClientModel::node
interfaces::Node & node() const
Definition: clientmodel.h:51
RPCExecutor::m_node
interfaces::Node & m_node
Definition: rpcconsole.cpp:87
RPCConsole::updateNetworkState
void updateNetworkState()
Update UI with latest network info from model.
Definition: rpcconsole.cpp:987
node.h
RPCConsole::CMD_REQUEST
@ CMD_REQUEST
Definition: rpcconsole.h:64
PeerTableModel::Subversion
@ Subversion
Definition: peertablemodel.h:65
ClientModel::blocksDir
QString blocksDir() const
Definition: clientmodel.cpp:197
RPCTimerBase
Opaque base class for timers returned by NewTimerFunc.
Definition: server.h:92
GUIUtil::openDebugLogfile
void openDebugLogfile()
Definition: guiutil.cpp:401
BerkeleyDatabaseVersion
std::string BerkeleyDatabaseVersion()
Definition: bdb.cpp:806
RPCConsole::showOrHideBanTableIfRequired
void showOrHideBanTableIfRequired()
Hides ban table if no bans are present.
Definition: rpcconsole.cpp:1455
CNodeStateStats::nSyncHeight
int nSyncHeight
Definition: net_processing.h:240
RPCConsole::autoCompleter
QCompleter * autoCompleter
Definition: rpcconsole.h:172
RPCConsole::CMD_ERROR
@ CMD_ERROR
Definition: rpcconsole.h:64
categoryClass
static QString categoryClass(int category)
Definition: rpcconsole.cpp:850
interfaces::Node::disconnectByAddress
virtual bool disconnectByAddress(const CNetAddr &net_addr)=0
Disconnect node by address.
RPCConsole::setTrafficGraphRange
void setTrafficGraphRange(int mins)
Definition: rpcconsole.cpp:1164
RPCConsole::RPCParseCommandLine
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).
Definition: rpcconsole.cpp:146
RPCConvertValues
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
Definition: client.cpp:218
CNodeStats::m_mapped_as
uint32_t m_mapped_as
Definition: net.h:792
bdb.h
chainparams.h
UniValue::write
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
Definition: univalue_write.cpp:159
RPCConsole::ui
Ui::RPCConsole *const ui
Definition: rpcconsole.h:161
ClientModel::getStatusBarWarnings
QString getStatusBarWarnings() const
Return warnings to be displayed in status bar.
Definition: clientmodel.cpp:161
RPCConsole::fontSmaller
void fontSmaller()
Definition: rpcconsole.cpp:870
PeerTableModel::Address
@ Address
Definition: peertablemodel.h:61
GUIUtil::formatPingTime
QString formatPingTime(int64_t ping_usec)
Definition: guiutil.cpp:818
ClientModel::CONNECTIONS_OUT
@ CONNECTIONS_OUT
Definition: clientmodel.h:43
BanTableModel::Bantime
@ Bantime
Definition: bantablemodel.h:50
QtRPCTimerBase::timer
QTimer timer
Definition: rpcconsole.cpp:104
UniValue
Definition: univalue.h:23
QtRPCTimerInterface::NewTimer
RPCTimerBase * NewTimer(std::function< void()> &func, int64_t millis) override
Factory function for timers.
Definition: rpcconsole.cpp:112
RPCConsole::setMempoolSize
void setMempoolSize(long numberOfTxs, size_t dynUsage)
Set size (number of transactions and memory usage) of the mempool in the UI.
Definition: rpcconsole.cpp:1026
CNodeStats::nTimeConnected
int64_t nTimeConnected
Definition: net.h:766
rpcconsole.h
GUIUtil::fixedPitchFont
QFont fixedPitchFont()
Definition: guiutil.cpp:76
RPCConsole::tabShortcut
QKeySequence tabShortcut(TabTypes tab_type) const
Definition: rpcconsole.cpp:1473
RPCConsole::peerLayoutChanged
void peerLayoutChanged()
Handle updated peer information.
Definition: rpcconsole.cpp:1204
RPCConsole::cachedNodeids
QList< NodeId > cachedNodeids
Definition: rpcconsole.h:166
RPCConsole::addWallet
void addWallet(WalletModel *const walletModel)
UniValue::get_str
const std::string & get_str() const
Definition: univalue_get.cpp:98
RPCConsole::updateTrafficStats
void updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
update traffic statistics
Definition: rpcconsole.cpp:1169
url
const char * url
Definition: rpcconsole.cpp:52
strencodings.h
UniValue::isStr
bool isStr() const
Definition: univalue.h:93
CNodeStats::addr
CAddress addr
Definition: net.h:787
GUIUtil::formatTimeOffset
QString formatTimeOffset(int64_t nTimeOffset)
Definition: guiutil.cpp:825
RPCConsole::consoleFontSize
int consoleFontSize
Definition: rpcconsole.h:171
RPCConsole::updateAlerts
void updateAlerts(const QString &warnings)
Definition: rpcconsole.cpp:1488
RPCConsole::setNetworkActive
void setNetworkActive(bool networkActive)
Set network state shown in the UI.
Definition: rpcconsole.cpp:1014
RPCConsole::scrollToEnd
void scrollToEnd()
Scroll console view to end.
Definition: rpcconsole.cpp:1153
CNodeStats::nSendBytes
uint64_t nSendBytes
Definition: net.h:774
CNodeStats::nLastRecv
int64_t nLastRecv
Definition: net.h:762
ClientModel::getPeerTableModel
PeerTableModel * getPeerTableModel()
Definition: clientmodel.cpp:169
RPCConsole::removeWallet
void removeWallet(WalletModel *const walletModel)
RPCConsole::showPeersTableContextMenu
void showPeersTableContextMenu(const QPoint &point)
Show custom context menu on Peers tab.
Definition: rpcconsole.cpp:1369
RPCConsole::setFontSize
void setFontSize(int newSize)
Definition: rpcconsole.cpp:874
PlatformStyle::SingleColorImage
QImage SingleColorImage(const QString &filename) const
Colorize an image (given filename) with the icon color.
Definition: platformstyle.cpp:90
RPCConsole::RPCConsole
RPCConsole(interfaces::Node &node, const PlatformStyle *platformStyle, QWidget *parent)
Definition: rpcconsole.cpp:510
RPCConsole::cmdRequest
void cmdRequest(const QString &command, const WalletModel *wallet_model)
RPCConsole::m_last_wallet_model
WalletModel * m_last_wallet_model
Definition: rpcconsole.h:174
PlatformStyle::getImagesOnButtons
bool getImagesOnButtons() const
Definition: platformstyle.h:20
RPCConsole::setClientModel
void setClientModel(ClientModel *model=nullptr, int bestblock_height=0, int64_t bestblock_date=0, double verification_progress=0.0)
Definition: rpcconsole.cpp:647
CNodeStats::addrName
std::string addrName
Definition: net.h:768
ClientModel::bytesChanged
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut)
RPCConsole::CMD_REPLY
@ CMD_REPLY
Definition: rpcconsole.h:64
util::ThreadRename
void ThreadRename(std::string &&)
Rename a thread both in terms of an internal (in-memory) name as well as its system thread name.
Definition: threadnames.cpp:48
GetSystemTimeInSeconds
int64_t GetSystemTimeInSeconds()
Returns the system time (not mockable)
Definition: time.cpp:75
RPCConsole::showEvent
void showEvent(QShowEvent *event) override
Definition: rpcconsole.cpp:1347
RPCConsole::on_tabWidget_currentChanged
void on_tabWidget_currentChanged(int index)
Definition: rpcconsole.cpp:1143
univalue.h
QtRPCTimerInterface::Name
const char * Name() override
Implementation name.
Definition: rpcconsole.cpp:111
db.h
RPCConsole::disconnectSelectedNode
void disconnectSelectedNode()
Disconnect a selected node on the Peers tab.
Definition: rpcconsole.cpp:1383
CNodeCombinedStats::fNodeStateStatsAvailable
bool fNodeStateStatsAvailable
Definition: peertablemodel.h:29
CNodeStats::m_permissionFlags
NetPermissionFlags m_permissionFlags
Definition: net.h:778
interfaces::Node::listRpcCommands
virtual std::vector< std::string > listRpcCommands()=0
List rpc commands.
RPCConsole
Local Bitcoin RPC console.
Definition: rpcconsole.h:36
CONSOLE_HISTORY
const int CONSOLE_HISTORY
Definition: rpcconsole.cpp:46
CNodeStats::m_ping_usec
int64_t m_ping_usec
Definition: net.h:780
RPCConsole::BANSUBNET_COLUMN_WIDTH
@ BANSUBNET_COLUMN_WIDTH
Definition: rpcconsole.h:155
CNodeStats::nStartingHeight
int nStartingHeight
Definition: net.h:773
CSubNet
Definition: netaddress.h:465
ClientModel::formatFullVersion
QString formatFullVersion() const
Definition: clientmodel.cpp:177
WalletModel::getWalletName
QString getWalletName() const
Definition: walletmodel.cpp:518
RPCConsole::PING_COLUMN_WIDTH
@ PING_COLUMN_WIDTH
Definition: rpcconsole.h:154
RPCConsole::showBanTableContextMenu
void showBanTableContextMenu(const QPoint &point)
Show custom context menu on Bans tab.
Definition: rpcconsole.cpp:1376
RPCConsole::SUBVERSION_COLUMN_WIDTH
@ SUBVERSION_COLUMN_WIDTH
Definition: rpcconsole.h:153
CNodeCombinedStats
Definition: peertablemodel.h:26
QtRPCTimerInterface
Definition: rpcconsole.cpp:108
GUIUtil::formatBytes
QString formatBytes(uint64_t bytes)
Definition: guiutil.cpp:859
RPCConsole::BANTIME_COLUMN_WIDTH
@ BANTIME_COLUMN_WIDTH
Definition: rpcconsole.h:156
GUIUtil::formatServicesStr
QString formatServicesStr(quint64 mask)
Definition: guiutil.cpp:802
RPCConsole::hideEvent
void hideEvent(QHideEvent *event) override
Definition: rpcconsole.cpp:1358
UniValue::isArray
bool isArray() const
Definition: univalue.h:95
RPCConsole::m_node
interfaces::Node & m_node
Definition: rpcconsole.h:160
interfaces::Node::unban
virtual bool unban(const CSubNet &ip)=0
Unban node.
RPCConsole::thread
QThread thread
Definition: rpcconsole.h:173
RPCConsole::TabTypes::GRAPH
@ GRAPH
PeerTableModel::getNodeStats
const CNodeCombinedStats * getNodeStats(int idx)
Definition: peertablemodel.cpp:208
interfaces::Node
Top-level interface for a bitcoin node (bitcoind process).
Definition: node.h:55
RPCConsole::tabTitle
QString tabTitle(TabTypes tab_type) const
Definition: rpcconsole.cpp:1469
RPCConsole::~RPCConsole
~RPCConsole()
Definition: rpcconsole.cpp:584
CNodeStats::addrLocal
std::string addrLocal
Definition: net.h:785
BanTableModel::shouldShow
bool shouldShow()
Definition: bantablemodel.cpp:167
PeerTableModel::Ping
@ Ping
Definition: peertablemodel.h:62
RPCConsole::updateNodeDetail
void updateNodeDetail(const CNodeCombinedStats *stats)
show detailed information on ui about selected node
Definition: rpcconsole.cpp:1262
IsDigit
constexpr bool IsDigit(char c)
Tests if the given character is a decimal digit.
Definition: strencodings.h:86
platformstyle.h
RPCConsole::history
QStringList history
Definition: rpcconsole.h:163
system.h
m_node
NodeContext & m_node
Definition: chain.cpp:485
RPCConsole::TabTypes
TabTypes
Definition: rpcconsole.h:66
TrafficGraphWidget::clear
void clear()
Definition: trafficgraphwidget.cpp:167
RPCConsole::cmdBeforeBrowsing
QString cmdBeforeBrowsing
Definition: rpcconsole.h:165
RPCExecutor
Definition: rpcconsole.cpp:75
ClientModel
Model for Bitcoin network client.
Definition: clientmodel.h:36
RPCConsole::eventFilter
virtual bool eventFilter(QObject *obj, QEvent *event) override
Definition: rpcconsole.cpp:592
Ui
Definition: addressbookpage.h:14
GUIUtil::HtmlEscape
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:240
RPCConsole::setTabFocus
void setTabFocus(enum TabTypes tabType)
set which tab has the focus (is visible)
Definition: rpcconsole.cpp:1465
UniValue::get_int
int get_int() const
Definition: univalue_get.cpp:105
RPCConsole::on_lineEdit_returnPressed
void on_lineEdit_returnPressed()
Definition: rpcconsole.cpp:1038
ClientModel::formatSubVersion
QString formatSubVersion() const
Definition: clientmodel.cpp:181
RPCConsole::peersTableContextMenu
QMenu * peersTableContextMenu
Definition: rpcconsole.h:169
QtRPCTimerInterface::~QtRPCTimerInterface
~QtRPCTimerInterface()
Definition: rpcconsole.cpp:110
CNodeStats::nServices
ServiceFlags nServices
Definition: net.h:759
ClientModel::formatClientStartupTime
QString formatClientStartupTime() const
Definition: clientmodel.cpp:189
CNodeStats::nVersion
int nVersion
Definition: net.h:769
QtRPCTimerBase::QtRPCTimerBase
QtRPCTimerBase(std::function< void()> &_func, int64_t millis)
Definition: rpcconsole.cpp:96
ClientModel::getNumConnections
int getNumConnections(NumConnections flags=CONNECTIONS_ALL) const
Return number of connections, default is in- and outbound (total)
Definition: clientmodel.cpp:68
PeerTableModel::startAutoRefresh
void startAutoRefresh()
Definition: peertablemodel.cpp:120
RPCConsole::RPCExecuteCommandLine
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
interfaces::Node::rpcSetTimerInterfaceIfUnset
virtual void rpcSetTimerInterfaceIfUnset(RPCTimerInterface *iface)=0
Set RPC timer interface if unset.
RPCConsole::message
void message(int category, const QString &msg)
Append the message to the message widget.
Definition: rpcconsole.h:107
UniValue::push_back
bool push_back(const UniValue &val)
Definition: univalue.cpp:108
Params
const CChainParams & Params()
Return the currently selected parameters.
Definition: chainparams.cpp:506
CNodeStats::cleanSubVer
std::string cleanSubVer
Definition: net.h:770
CSubNet::IsValid
bool IsValid() const
Definition: netaddress.cpp:1155
ClientModel::dataDir
QString dataDir() const
Definition: clientmodel.cpp:193
RPCConsole::on_openDebugLogfileButton_clicked
void on_openDebugLogfileButton_clicked()
open the debug.log from the current datadir
Definition: rpcconsole.cpp:1149
FONT_RANGE
const QSize FONT_RANGE(4, 40)
config.h
GUIUtil::formatDurationStr
QString formatDurationStr(int secs)
Definition: guiutil.cpp:779
NodeId
int64_t NodeId
Definition: nodeid.h:10
RPCConsole::browseHistory
void browseHistory(int offset)
Go forward or back in history.
Definition: rpcconsole.cpp:1099
RPCExecutor::reply
void reply(int category, const QString &command)
RPCConsole::historyPtr
int historyPtr
Definition: rpcconsole.h:164
RPCConsole::on_sldGraphRange_valueChanged
void on_sldGraphRange_valueChanged(int value)
change the time range of the network traffic graph
Definition: rpcconsole.cpp:1158
bantablemodel.h
RPCExecutor::request
void request(const QString &command, const WalletModel *wallet_model)
Definition: rpcconsole.cpp:443
interfaces::Node::rpcUnsetTimerInterface
virtual void rpcUnsetTimerInterface(RPCTimerInterface *iface)=0
Unset RPC timer interface.
netbase.h
RPCConsole::setNumBlocks
void setNumBlocks(int count, const QDateTime &blockDate, double nVerificationProgress, bool headers)
Set number of blocks and last block date shown in the UI.
Definition: rpcconsole.cpp:1018
GUIUtil::handleCloseWindowShortcut
void handleCloseWindowShortcut(QWidget *w)
Definition: guiutil.cpp:396
find_value
const UniValue & find_value(const UniValue &obj, const std::string &name)
Definition: univalue.cpp:234
RPCConsole::fontBigger
void fontBigger()
Definition: rpcconsole.cpp:866
GUIUtil::getEntryData
QList< QModelIndex > getEntryData(const QAbstractItemView *view, int column)
Return a field of the currently selected entry as a QString.
Definition: guiutil.cpp:264
PeerTableModel::getRowByNodeId
int getRowByNodeId(NodeId nodeid)
Definition: peertablemodel.cpp:218
interfaces::Node::executeRpc
virtual UniValue executeRpc(Config &config, const std::string &command, const UniValue &params, const std::string &uri)=0
Execute rpc command.
WalletModel::getDisplayName
QString getDisplayName() const
Definition: walletmodel.cpp:522
CNodeStats::nRecvBytes
uint64_t nRecvBytes
Definition: net.h:776
interfaces::Node::getTotalBytesRecv
virtual int64_t getTotalBytesRecv()=0
Get total bytes recv.
server.h
PlatformStyle
Definition: platformstyle.h:13
RPCConsole::unbanSelectedNode
void unbanSelectedNode()
Unban a selected node on the Bans tab.
Definition: rpcconsole.cpp:1428
PeerTableModel::stopAutoRefresh
void stopAutoRefresh()
Definition: peertablemodel.cpp:124
threadnames.h
CNodeStats::fInbound
bool fInbound
Definition: net.h:771
QtRPCTimerBase::~QtRPCTimerBase
~QtRPCTimerBase()
Definition: rpcconsole.cpp:101
RPCConsole::clear
void clear(bool clearHistory=true)
Definition: rpcconsole.cpp:904
RPCConsole::rpcTimerInterface
RPCTimerInterface * rpcTimerInterface
Definition: rpcconsole.h:168
interfaces::Node::getTotalBytesSent
virtual int64_t getTotalBytesSent()=0
Get total bytes sent.
RPCConsole::peerSelected
void peerSelected(const QItemSelection &selected, const QItemSelection &deselected)
Handle selection of peer in peers list.
Definition: rpcconsole.cpp:1175
RPCConsole::banSelectedNode
void banSelectedNode(int bantime)
Ban a selected node on the Peers tab.
Definition: rpcconsole.cpp:1397
BanTableModel::refresh
void refresh()
Definition: bantablemodel.cpp:155
QtRPCTimerBase::func
std::function< void()> func
Definition: rpcconsole.cpp:105
CNodeStats::m_ping_wait_usec
int64_t m_ping_wait_usec
Definition: net.h:781
client.h
RPCConsole::peerLayoutAboutToChange
void peerLayoutAboutToChange()
Handle selection caching before update.
Definition: rpcconsole.cpp:1192
RPCConsole::clientModel
ClientModel * clientModel
Definition: rpcconsole.h:162
ClientModel::networkActiveChanged
void networkActiveChanged(bool networkActive)
RPCConsole::banTableContextMenu
QMenu * banTableContextMenu
Definition: rpcconsole.h:170
clientmodel.h
RPCConsole::TabTypes::INFO
@ INFO
LookupSubNet
bool LookupSubNet(const std::string &strSubnet, CSubNet &ret)
Parse and resolve a specified subnet string into the appropriate internal representation.
Definition: netbase.cpp:891
BanTableModel::Address
@ Address
Definition: bantablemodel.h:50
GlobalConfig
Definition: config.h:33
UniValue::isObject
bool isObject() const
Definition: univalue.h:96
ClientModel::getBanTableModel
BanTableModel * getBanTableModel()
Definition: clientmodel.cpp:173
RPCConsole::TabTypes::PEERS
@ PEERS
CNodeCombinedStats::nodeStateStats
CNodeStateStats nodeStateStats
Definition: peertablemodel.h:28