Raven Core  3.0.0
P2P Digital Currency
rpcconsole.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2016 The Bitcoin Core developers
2 // Copyright (c) 2017-2019 The Raven Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
6 #if defined(HAVE_CONFIG_H)
7 #include "config/raven-config.h"
8 #endif
9 
10 #include "rpcconsole.h"
11 #include "ui_debugwindow.h"
12 #include "sendcoinsdialog.h"
13 
14 #include "bantablemodel.h"
15 #include "clientmodel.h"
16 #include "guiutil.h"
17 #include "platformstyle.h"
18 #include "chainparams.h"
19 #include "netbase.h"
20 #include "rpc/server.h"
21 #include "rpc/client.h"
22 #include "util.h"
23 
24 #include <openssl/crypto.h>
25 
26 #include <univalue.h>
27 
28 #ifdef ENABLE_WALLET
29 #include <db_cxx.h>
30 #include <wallet/wallet.h>
31 #endif
32 
33 #include <QDir>
34 #include <QDesktopWidget>
35 #include <QKeyEvent>
36 #include <QMenu>
37 #include <QMessageBox>
38 #include <QScrollBar>
39 #include <QSettings>
40 #include <QSignalMapper>
41 #include <QThread>
42 #include <QTime>
43 #include <QTimer>
44 #include <QStringList>
45 
46 #if QT_VERSION < 0x050000
47 #include <QUrl>
48 #endif
49 
50 // TODO: add a scrollback limit, as there is currently none
51 // TODO: make it possible to filter out categories (esp debug messages when implemented)
52 // TODO: receive errors and debug messages through ClientModel
53 
54 const int CONSOLE_HISTORY = 50;
56 const QSize FONT_RANGE(4, 40);
57 const char fontSizeSettingsKey[] = "consoleFontSize";
58 
59 // Repair parameters
60 const QString RESCAN("-rescan");
61 const QString ZAPTXES1("-zapwallettxes=1");
62 const QString REINDEX("-reindex");
63 
64 const struct {
65  const char *url;
66  const char *source;
67 } ICON_MAPPING[] = {
68  {"cmd-request", ":/icons/tx_input"},
69  {"cmd-reply", ":/icons/tx_output"},
70  {"cmd-error", ":/icons/tx_output"},
71  {"misc", ":/icons/tx_inout"},
72  {nullptr, nullptr}
73 };
74 
75 namespace {
76 
77 // don't add private key handling cmd's to the history
78 const QStringList historyFilter = QStringList()
79  << "importprivkey"
80  << "importmulti"
81  << "signmessagewithprivkey"
82  << "signrawtransaction"
83  << "walletpassphrase"
84  << "walletpassphrasechange"
85  << "encryptwallet";
86 
87 }
88 
89 /* Object for executing console RPC commands in a separate thread.
90 */
91 class RPCExecutor : public QObject
92 {
93  Q_OBJECT
94 
95 public Q_SLOTS:
96  void request(const QString &command);
97 
98 Q_SIGNALS:
99  void reply(int category, const QString &command);
100 };
101 
105 class QtRPCTimerBase: public QObject, public RPCTimerBase
106 {
107  Q_OBJECT
108 public:
109  QtRPCTimerBase(std::function<void(void)>& _func, int64_t millis):
110  func(_func)
111  {
112  timer.setSingleShot(true);
113  connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
114  timer.start(millis);
115  }
117 private Q_SLOTS:
118  void timeout() { func(); }
119 private:
120  QTimer timer;
121  std::function<void(void)> func;
122 };
123 
125 {
126 public:
128  const char *Name() { return "Qt"; }
129  RPCTimerBase* NewTimer(std::function<void(void)>& func, int64_t millis)
130  {
131  return new QtRPCTimerBase(func, millis);
132  }
133 };
134 
135 
136 #include "rpcconsole.moc"
137 
157 bool RPCConsole::RPCParseCommandLine(std::string &strResult, const std::string &strCommand, const bool fExecute, std::string * const pstrFilteredOut)
158 {
159  std::vector< std::vector<std::string> > stack;
160  stack.push_back(std::vector<std::string>());
161 
162  enum CmdParseState
163  {
164  STATE_EATING_SPACES,
165  STATE_EATING_SPACES_IN_ARG,
166  STATE_EATING_SPACES_IN_BRACKETS,
167  STATE_ARGUMENT,
168  STATE_SINGLEQUOTED,
169  STATE_DOUBLEQUOTED,
170  STATE_ESCAPE_OUTER,
171  STATE_ESCAPE_DOUBLEQUOTED,
172  STATE_COMMAND_EXECUTED,
173  STATE_COMMAND_EXECUTED_INNER
174  } state = STATE_EATING_SPACES;
175  std::string curarg;
176  UniValue lastResult;
177  unsigned nDepthInsideSensitive = 0;
178  size_t filter_begin_pos = 0, chpos;
179  std::vector<std::pair<size_t, size_t>> filter_ranges;
180 
181  auto add_to_current_stack = [&](const std::string& strArg) {
182  if (stack.back().empty() && (!nDepthInsideSensitive) && historyFilter.contains(QString::fromStdString(strArg), Qt::CaseInsensitive)) {
183  nDepthInsideSensitive = 1;
184  filter_begin_pos = chpos;
185  }
186  // Make sure stack is not empty before adding something
187  if (stack.empty()) {
188  stack.push_back(std::vector<std::string>());
189  }
190  stack.back().push_back(strArg);
191  };
192 
193  auto close_out_params = [&]() {
194  if (nDepthInsideSensitive) {
195  if (!--nDepthInsideSensitive) {
196  assert(filter_begin_pos);
197  filter_ranges.push_back(std::make_pair(filter_begin_pos, chpos));
198  filter_begin_pos = 0;
199  }
200  }
201  stack.pop_back();
202  };
203 
204  std::string strCommandTerminated = strCommand;
205  if (strCommandTerminated.back() != '\n')
206  strCommandTerminated += "\n";
207  for (chpos = 0; chpos < strCommandTerminated.size(); ++chpos)
208  {
209  char ch = strCommandTerminated[chpos];
210  switch(state)
211  {
212  case STATE_COMMAND_EXECUTED_INNER:
213  case STATE_COMMAND_EXECUTED:
214  {
215  bool breakParsing = true;
216  switch(ch)
217  {
218  case '[': curarg.clear(); state = STATE_COMMAND_EXECUTED_INNER; break;
219  default:
220  if (state == STATE_COMMAND_EXECUTED_INNER)
221  {
222  if (ch != ']')
223  {
224  // append char to the current argument (which is also used for the query command)
225  curarg += ch;
226  break;
227  }
228  if (curarg.size() && fExecute)
229  {
230  // if we have a value query, query arrays with index and objects with a string key
231  UniValue subelement;
232  if (lastResult.isArray())
233  {
234  for(char argch: curarg)
235  if (!std::isdigit(argch))
236  throw std::runtime_error("Invalid result query");
237  subelement = lastResult[atoi(curarg.c_str())];
238  }
239  else if (lastResult.isObject())
240  subelement = find_value(lastResult, curarg);
241  else
242  throw std::runtime_error("Invalid result query"); //no array or object: abort
243  lastResult = subelement;
244  }
245 
246  state = STATE_COMMAND_EXECUTED;
247  break;
248  }
249  // don't break parsing when the char is required for the next argument
250  breakParsing = false;
251 
252  // pop the stack and return the result to the current command arguments
253  close_out_params();
254 
255  // don't stringify the json in case of a string to avoid doublequotes
256  if (lastResult.isStr())
257  curarg = lastResult.get_str();
258  else
259  curarg = lastResult.write(2);
260 
261  // if we have a non empty result, use it as stack argument otherwise as general result
262  if (curarg.size())
263  {
264  if (stack.size())
265  add_to_current_stack(curarg);
266  else
267  strResult = curarg;
268  }
269  curarg.clear();
270  // assume eating space state
271  state = STATE_EATING_SPACES;
272  }
273  if (breakParsing)
274  break;
275  }
276  case STATE_ARGUMENT: // In or after argument
277  case STATE_EATING_SPACES_IN_ARG:
278  case STATE_EATING_SPACES_IN_BRACKETS:
279  case STATE_EATING_SPACES: // Handle runs of whitespace
280  switch(ch)
281  {
282  case '"': state = STATE_DOUBLEQUOTED; break;
283  case '\'': state = STATE_SINGLEQUOTED; break;
284  case '\\': state = STATE_ESCAPE_OUTER; break;
285  case '(': case ')': case '\n':
286  if (state == STATE_EATING_SPACES_IN_ARG)
287  throw std::runtime_error("Invalid Syntax");
288  if (state == STATE_ARGUMENT)
289  {
290  if (ch == '(' && stack.size() && stack.back().size() > 0)
291  {
292  if (nDepthInsideSensitive) {
293  ++nDepthInsideSensitive;
294  }
295  stack.push_back(std::vector<std::string>());
296  }
297 
298  // don't allow commands after executed commands on baselevel
299  if (!stack.size())
300  throw std::runtime_error("Invalid Syntax");
301 
302  add_to_current_stack(curarg);
303  curarg.clear();
304  state = STATE_EATING_SPACES_IN_BRACKETS;
305  }
306  if ((ch == ')' || ch == '\n') && stack.size() > 0)
307  {
308  if (fExecute) {
309  // Convert argument list to JSON objects in method-dependent way,
310  // and pass it along with the method name to the dispatcher.
311  JSONRPCRequest req;
312  req.params = RPCConvertValues(stack.back()[0], std::vector<std::string>(stack.back().begin() + 1, stack.back().end()));
313  req.strMethod = stack.back()[0];
314 #ifdef ENABLE_WALLET
315  // TODO: Move this logic to WalletModel
316  if (!vpwallets.empty()) {
317  // in Qt, use always the wallet with index 0 when running with multiple wallets
318  QByteArray encodedName = QUrl::toPercentEncoding(QString::fromStdString(vpwallets[0]->GetName()));
319  req.URI = "/wallet/"+std::string(encodedName.constData(), encodedName.length());
320  }
321 #endif
322  lastResult = tableRPC.execute(req);
323  }
324 
325  state = STATE_COMMAND_EXECUTED;
326  curarg.clear();
327  }
328  break;
329  case ' ': case ',': case '\t':
330  if(state == STATE_EATING_SPACES_IN_ARG && curarg.empty() && ch == ',')
331  throw std::runtime_error("Invalid Syntax");
332 
333  else if(state == STATE_ARGUMENT) // Space ends argument
334  {
335  add_to_current_stack(curarg);
336  curarg.clear();
337  }
338  if ((state == STATE_EATING_SPACES_IN_BRACKETS || state == STATE_ARGUMENT) && ch == ',')
339  {
340  state = STATE_EATING_SPACES_IN_ARG;
341  break;
342  }
343  state = STATE_EATING_SPACES;
344  break;
345  default: curarg += ch; state = STATE_ARGUMENT;
346  }
347  break;
348  case STATE_SINGLEQUOTED: // Single-quoted string
349  switch(ch)
350  {
351  case '\'': state = STATE_ARGUMENT; break;
352  default: curarg += ch;
353  }
354  break;
355  case STATE_DOUBLEQUOTED: // Double-quoted string
356  switch(ch)
357  {
358  case '"': state = STATE_ARGUMENT; break;
359  case '\\': state = STATE_ESCAPE_DOUBLEQUOTED; break;
360  default: curarg += ch;
361  }
362  break;
363  case STATE_ESCAPE_OUTER: // '\' outside quotes
364  curarg += ch; state = STATE_ARGUMENT;
365  break;
366  case STATE_ESCAPE_DOUBLEQUOTED: // '\' in double-quoted text
367  if(ch != '"' && ch != '\\') curarg += '\\'; // keep '\' for everything but the quote and '\' itself
368  curarg += ch; state = STATE_DOUBLEQUOTED;
369  break;
370  }
371  }
372  if (pstrFilteredOut) {
373  if (STATE_COMMAND_EXECUTED == state) {
374  assert(!stack.empty());
375  close_out_params();
376  }
377  *pstrFilteredOut = strCommand;
378  for (auto i = filter_ranges.rbegin(); i != filter_ranges.rend(); ++i) {
379  pstrFilteredOut->replace(i->first, i->second - i->first, "(…)");
380  }
381  }
382  switch(state) // final state
383  {
384  case STATE_COMMAND_EXECUTED:
385  if (lastResult.isStr())
386  strResult = lastResult.get_str();
387  else
388  strResult = lastResult.write(2);
389  case STATE_ARGUMENT:
390  case STATE_EATING_SPACES:
391  return true;
392  default: // ERROR to end in one of the other states
393  return false;
394  }
395 }
396 
397 void RPCExecutor::request(const QString &command)
398 {
399  try
400  {
401  std::string result;
402  std::string executableCommand = command.toStdString() + "\n";
403  if(!RPCConsole::RPCExecuteCommandLine(result, executableCommand))
404  {
405  Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Parse error: unbalanced ' or \""));
406  return;
407  }
408  Q_EMIT reply(RPCConsole::CMD_REPLY, QString::fromStdString(result));
409  }
410  catch (UniValue& objError)
411  {
412  try // Nice formatting for standard-format error
413  {
414  int code = find_value(objError, "code").get_int();
415  std::string message = find_value(objError, "message").get_str();
416  Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(message) + " (code " + QString::number(code) + ")");
417  }
418  catch (const std::runtime_error&) // raised when converting to invalid type, i.e. missing code or message
419  { // Show raw JSON object
420  Q_EMIT reply(RPCConsole::CMD_ERROR, QString::fromStdString(objError.write()));
421  }
422  }
423  catch (const std::exception& e)
424  {
425  Q_EMIT reply(RPCConsole::CMD_ERROR, QString("Error: ") + QString::fromStdString(e.what()));
426  }
427 }
428 
429 RPCConsole::RPCConsole(const PlatformStyle *_platformStyle, QWidget *parent) :
430  QWidget(parent),
431  ui(new Ui::RPCConsole),
432  clientModel(0),
433  historyPtr(0),
434  platformStyle(_platformStyle),
435  peersTableContextMenu(0),
436  banTableContextMenu(0),
437  consoleFontSize(0)
438 {
439  ui->setupUi(this);
440  QSettings settings;
441  if (!restoreGeometry(settings.value("RPCConsoleWindowGeometry").toByteArray())) {
442  // Restore failed (perhaps missing setting), center the window
443  move(QApplication::desktop()->availableGeometry().center() - frameGeometry().center());
444  }
445 
446  ui->openDebugLogfileButton->setToolTip(ui->openDebugLogfileButton->toolTip().arg(tr(PACKAGE_NAME)));
447 
449  ui->openDebugLogfileButton->setIcon(platformStyle->SingleColorIcon(":/icons/export"));
450  }
451  ui->clearButton->setIcon(platformStyle->SingleColorIcon(":/icons/remove"));
452  ui->fontBiggerButton->setIcon(platformStyle->SingleColorIcon(":/icons/fontbigger"));
453  ui->fontSmallerButton->setIcon(platformStyle->SingleColorIcon(":/icons/fontsmaller"));
454 
455  // Install event filter for up and down arrow
456  ui->lineEdit->installEventFilter(this);
457  ui->messagesWidget->installEventFilter(this);
458 
459  connect(ui->clearButton, SIGNAL(clicked()), this, SLOT(clear()));
460  connect(ui->fontBiggerButton, SIGNAL(clicked()), this, SLOT(fontBigger()));
461  connect(ui->fontSmallerButton, SIGNAL(clicked()), this, SLOT(fontSmaller()));
462  connect(ui->btnClearTrafficGraph, SIGNAL(clicked()), ui->trafficGraph, SLOT(clear()));
463 
464  // Wallet Repair Buttons
465  connect(ui->btn_rescan, SIGNAL(clicked()), this, SLOT(walletRescan()));
466  connect(ui->btn_zapwallettxes1, SIGNAL(clicked()), this, SLOT(walletZaptxes1()));
467  connect(ui->btn_reindex, SIGNAL(clicked()), this, SLOT(walletReindex()));
468 
469  // set library version labels
470 #ifdef ENABLE_WALLET
471  ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0));
472  std::string walletPath = GetDataDir().string();
473  walletPath += QDir::separator().toLatin1() + gArgs.GetArg("-wallet", "wallet.dat");
474  ui->wallet_path->setText(QString::fromStdString(walletPath));
475 #else
476  ui->label_berkeleyDBVersion->hide();
477  ui->berkeleyDBVersion->hide();
478 #endif
479  // Register RPC timer interface
481  // avoid accidentally overwriting an existing, non QTThread
482  // based timer interface
484 
486 
487  ui->detailWidget->hide();
488  ui->peerHeading->setText(tr("Select a peer to view detailed information."));
489 
490  consoleFontSize = settings.value(fontSizeSettingsKey, QFontInfo(QFont()).pointSize()).toInt();
491  clear();
492 }
493 
495 {
496  QSettings settings;
497  settings.setValue("RPCConsoleWindowGeometry", saveGeometry());
499  delete rpcTimerInterface;
500  delete ui;
501 }
502 
503 bool RPCConsole::eventFilter(QObject* obj, QEvent *event)
504 {
505  if(event->type() == QEvent::KeyPress) // Special key handling
506  {
507  QKeyEvent *keyevt = static_cast<QKeyEvent*>(event);
508  int key = keyevt->key();
509  Qt::KeyboardModifiers mod = keyevt->modifiers();
510  switch(key)
511  {
512  case Qt::Key_Up: if(obj == ui->lineEdit) { browseHistory(-1); return true; } break;
513  case Qt::Key_Down: if(obj == ui->lineEdit) { browseHistory(1); return true; } break;
514  case Qt::Key_PageUp: /* pass paging keys to messages widget */
515  case Qt::Key_PageDown:
516  if(obj == ui->lineEdit)
517  {
518  QApplication::postEvent(ui->messagesWidget, new QKeyEvent(*keyevt));
519  return true;
520  }
521  break;
522  case Qt::Key_Return:
523  case Qt::Key_Enter:
524  // forward these events to lineEdit
525  if(obj == autoCompleter->popup()) {
526  QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
527  return true;
528  }
529  break;
530  default:
531  // Typing in messages widget brings focus to line edit, and redirects key there
532  // Exclude most combinations and keys that emit no text, except paste shortcuts
533  if(obj == ui->messagesWidget && (
534  (!mod && !keyevt->text().isEmpty() && key != Qt::Key_Tab) ||
535  ((mod & Qt::ControlModifier) && key == Qt::Key_V) ||
536  ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert)))
537  {
538  ui->lineEdit->setFocus();
539  QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
540  return true;
541  }
542  }
543  }
544  return QWidget::eventFilter(obj, event);
545 }
546 
548 {
549  clientModel = model;
550  ui->trafficGraph->setClientModel(model);
552  // Keep up to date with client
554  connect(model, SIGNAL(numConnectionsChanged(int)), this, SLOT(setNumConnections(int)));
555 
556  setNumBlocks(model->getNumBlocks(), model->getLastBlockDate(), model->getVerificationProgress(nullptr), false);
557  connect(model, SIGNAL(numBlocksChanged(int,QDateTime,double,bool)), this, SLOT(setNumBlocks(int,QDateTime,double,bool)));
558 
560  connect(model, SIGNAL(networkActiveChanged(bool)), this, SLOT(setNetworkActive(bool)));
561 
563  connect(model, SIGNAL(bytesChanged(quint64,quint64)), this, SLOT(updateTrafficStats(quint64, quint64)));
564 
565  connect(model, SIGNAL(mempoolSizeChanged(long,size_t)), this, SLOT(setMempoolSize(long,size_t)));
566 
567  // set up peer table
568  ui->peerWidget->setModel(model->getPeerTableModel());
569  ui->peerWidget->verticalHeader()->hide();
570  ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
571  ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
572  ui->peerWidget->setSelectionMode(QAbstractItemView::ExtendedSelection);
573  ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu);
574  ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH);
575  ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH);
576  ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH);
577  ui->peerWidget->horizontalHeader()->setStretchLastSection(true);
578 
579  // create peer table context menu actions
580  QAction* disconnectAction = new QAction(tr("&Disconnect"), this);
581  QAction* banAction1h = new QAction(tr("Ban for") + " " + tr("1 &hour"), this);
582  QAction* banAction24h = new QAction(tr("Ban for") + " " + tr("1 &day"), this);
583  QAction* banAction7d = new QAction(tr("Ban for") + " " + tr("1 &week"), this);
584  QAction* banAction365d = new QAction(tr("Ban for") + " " + tr("1 &year"), this);
585 
586  // create peer table context menu
587  peersTableContextMenu = new QMenu(this);
588  peersTableContextMenu->addAction(disconnectAction);
589  peersTableContextMenu->addAction(banAction1h);
590  peersTableContextMenu->addAction(banAction24h);
591  peersTableContextMenu->addAction(banAction7d);
592  peersTableContextMenu->addAction(banAction365d);
593 
594  // Add a signal mapping to allow dynamic context menu arguments.
595  // We need to use int (instead of int64_t), because signal mapper only supports
596  // int or objects, which is okay because max bantime (1 year) is < int_max.
597  QSignalMapper* signalMapper = new QSignalMapper(this);
598  signalMapper->setMapping(banAction1h, 60*60);
599  signalMapper->setMapping(banAction24h, 60*60*24);
600  signalMapper->setMapping(banAction7d, 60*60*24*7);
601  signalMapper->setMapping(banAction365d, 60*60*24*365);
602  connect(banAction1h, SIGNAL(triggered()), signalMapper, SLOT(map()));
603  connect(banAction24h, SIGNAL(triggered()), signalMapper, SLOT(map()));
604  connect(banAction7d, SIGNAL(triggered()), signalMapper, SLOT(map()));
605  connect(banAction365d, SIGNAL(triggered()), signalMapper, SLOT(map()));
606  connect(signalMapper, SIGNAL(mapped(int)), this, SLOT(banSelectedNode(int)));
607 
608  // peer table context menu signals
609  connect(ui->peerWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showPeersTableContextMenu(const QPoint&)));
610  connect(disconnectAction, SIGNAL(triggered()), this, SLOT(disconnectSelectedNode()));
611 
612  // peer table signal handling - update peer details when selecting new node
613  connect(ui->peerWidget->selectionModel(), SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
614  this, SLOT(peerSelected(const QItemSelection &, const QItemSelection &)));
615  // peer table signal handling - update peer details when new nodes are added to the model
616  connect(model->getPeerTableModel(), SIGNAL(layoutChanged()), this, SLOT(peerLayoutChanged()));
617  // peer table signal handling - cache selected node ids
618  connect(model->getPeerTableModel(), SIGNAL(layoutAboutToBeChanged()), this, SLOT(peerLayoutAboutToChange()));
619 
620  // set up ban table
621  ui->banlistWidget->setModel(model->getBanTableModel());
622  ui->banlistWidget->verticalHeader()->hide();
623  ui->banlistWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
624  ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
625  ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection);
626  ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu);
627  ui->banlistWidget->setColumnWidth(BanTableModel::Address, BANSUBNET_COLUMN_WIDTH);
628  ui->banlistWidget->setColumnWidth(BanTableModel::Bantime, BANTIME_COLUMN_WIDTH);
629  ui->banlistWidget->horizontalHeader()->setStretchLastSection(true);
630 
631  // create ban table context menu action
632  QAction* unbanAction = new QAction(tr("&Unban"), this);
633 
634  // create ban table context menu
635  banTableContextMenu = new QMenu(this);
636  banTableContextMenu->addAction(unbanAction);
637 
638  // ban table context menu signals
639  connect(ui->banlistWidget, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(showBanTableContextMenu(const QPoint&)));
640  connect(unbanAction, SIGNAL(triggered()), this, SLOT(unbanSelectedNode()));
641 
642  // ban table signal handling - clear peer details when clicking a peer in the ban table
643  connect(ui->banlistWidget, SIGNAL(clicked(const QModelIndex&)), this, SLOT(clearSelectedNode()));
644  // ban table signal handling - ensure ban table is shown or hidden (if empty)
645  connect(model->getBanTableModel(), SIGNAL(layoutChanged()), this, SLOT(showOrHideBanTableIfRequired()));
647 
648  // Provide initial values
649  ui->clientVersion->setText(model->formatFullVersion());
650  ui->clientUserAgent->setText(model->formatSubVersion());
651  ui->dataDir->setText(model->dataDir());
652  ui->startupTime->setText(model->formatClientStartupTime());
653  ui->networkName->setText(QString::fromStdString(Params().NetworkIDString()));
654 
655  //Setup autocomplete and attach it
656  QStringList wordList;
657  std::vector<std::string> commandList = tableRPC.listCommands();
658  for (size_t i = 0; i < commandList.size(); ++i)
659  {
660  wordList << commandList[i].c_str();
661  wordList << ("help " + commandList[i]).c_str();
662  }
663 
664  wordList.sort();
665  autoCompleter = new QCompleter(wordList, this);
666  autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel);
667  ui->lineEdit->setCompleter(autoCompleter);
668  autoCompleter->popup()->installEventFilter(this);
669  // Start thread to execute RPC commands.
670  startExecutor();
671  }
672  if (!model) {
673  // Client model is being set to 0, this means shutdown() is about to be called.
674  // Make sure we clean up the executor thread
675  Q_EMIT stopExecutor();
676  thread.wait();
677  }
678 }
679 
680 static QString categoryClass(int category)
681 {
682  switch(category)
683  {
684  case RPCConsole::CMD_REQUEST: return "cmd-request"; break;
685  case RPCConsole::CMD_REPLY: return "cmd-reply"; break;
686  case RPCConsole::CMD_ERROR: return "cmd-error"; break;
687  default: return "misc";
688  }
689 }
690 
692 {
694 }
695 
697 {
699 }
700 
701 void RPCConsole::setFontSize(int newSize)
702 {
703  QSettings settings;
704 
705  //don't allow an insane font size
706  if (newSize < FONT_RANGE.width() || newSize > FONT_RANGE.height())
707  return;
708 
709  // temp. store the console content
710  QString str = ui->messagesWidget->toHtml();
711 
712  // replace font tags size in current content
713  str.replace(QString("font-size:%1pt").arg(consoleFontSize), QString("font-size:%1pt").arg(newSize));
714 
715  // store the new font size
716  consoleFontSize = newSize;
717  settings.setValue(fontSizeSettingsKey, consoleFontSize);
718 
719  // clear console (reset icon sizes, default stylesheet) and re-add the content
720  float oldPosFactor = 1.0 / ui->messagesWidget->verticalScrollBar()->maximum() * ui->messagesWidget->verticalScrollBar()->value();
721  clear(false);
722  ui->messagesWidget->setHtml(str);
723  ui->messagesWidget->verticalScrollBar()->setValue(oldPosFactor * ui->messagesWidget->verticalScrollBar()->maximum());
724 }
725 
728 {
730 }
731 
734 {
736 }
737 
740 {
741  QString questionString = tr("Are you sure you want to reindex?");
742  questionString.append(QString("<br /><br />This process may take a few hours."));
743 
744  SendConfirmationDialog confirmationDialog(tr("Confirm reindex"), questionString, 0, this);
745  confirmationDialog.exec();
746  QMessageBox::StandardButton retval = (QMessageBox::StandardButton)confirmationDialog.result();
747 
748  if(retval != QMessageBox::Yes)
749  {
750  return;
751  }
752 
754 }
755 
758 {
759  // Get command-line arguments and remove the application name
760  QStringList args = QApplication::arguments();
761  args.removeFirst();
762 
763  // Remove existing repair-options
764  args.removeAll(RESCAN);
765  args.removeAll(ZAPTXES1);
766  args.removeAll(REINDEX);
767 
768  // Append repair parameter to command line.
769  args.append(arg);
770 
771  // Send command-line arguments to RavenGUI::handleRestart()
772  Q_EMIT handleRestart(args);
773 }
774 
775 void RPCConsole::clear(bool clearHistory)
776 {
777  ui->messagesWidget->clear();
778  if(clearHistory)
779  {
780  history.clear();
781  historyPtr = 0;
782  }
783  ui->lineEdit->clear();
784  ui->lineEdit->setFocus();
785 
786  // Add smoothly scaled icon images.
787  // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
788  for(int i=0; ICON_MAPPING[i].url; ++i)
789  {
790  ui->messagesWidget->document()->addResource(
791  QTextDocument::ImageResource,
792  QUrl(ICON_MAPPING[i].url),
793  platformStyle->SingleColorImage(ICON_MAPPING[i].source).scaled(QSize(consoleFontSize*2, consoleFontSize*2), Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
794  }
795 
796  // Set default style sheet
797  QFontInfo fixedFontInfo(GUIUtil::fixedPitchFont());
798  ui->messagesWidget->document()->setDefaultStyleSheet(
799  QString(
800  "table { }"
801  "td.time { color: #808080; font-size: %2; padding-top: 3px; } "
802  "td.message { font-family: %1; font-size: %2; white-space:pre-wrap; } "
803  "td.cmd-request { color: #006060; } "
804  "td.cmd-error { color: red; } "
805  ".secwarning { color: red; }"
806  "b { color: #006060; } "
807  ).arg(fixedFontInfo.family(), QString("%1pt").arg(consoleFontSize))
808  );
809 
810 #ifdef Q_OS_MAC
811  QString clsKey = "(⌘)-L";
812 #else
813  QString clsKey = "Ctrl-L";
814 #endif
815 
816  message(CMD_REPLY, (tr("Welcome to the %1 RPC console.").arg(tr(PACKAGE_NAME)) + "<br>" +
817  tr("Use up and down arrows to navigate history, and %1 to clear screen.").arg("<b>"+clsKey+"</b>") + "<br>" +
818  tr("Type <b>help</b> for an overview of available commands.")) +
819  "<br><span class=\"secwarning\">" +
820  tr("WARNING: Scammers have been active, telling users to type commands here, stealing their wallet contents. Do not use this console without fully understanding the ramifications of a command.") +
821  "</span>",
822  true);
823 }
824 
825 void RPCConsole::keyPressEvent(QKeyEvent *event)
826 {
827  if(windowType() != Qt::Widget && event->key() == Qt::Key_Escape)
828  {
829  close();
830  }
831 }
832 
833 void RPCConsole::message(int category, const QString &message, bool html)
834 {
835  QTime time = QTime::currentTime();
836  QString timeString = time.toString();
837  QString out;
838  out += "<table><tr><td class=\"time\" width=\"65\">" + timeString + "</td>";
839  out += "<td class=\"icon\" width=\"32\"><img src=\"" + categoryClass(category) + "\"></td>";
840  out += "<td class=\"message " + categoryClass(category) + "\" valign=\"middle\">";
841  if(html)
842  out += message;
843  else
844  out += GUIUtil::HtmlEscape(message, false);
845  out += "</td></tr></table>";
846  ui->messagesWidget->append(out);
847 }
848 
850 {
851  QString connections = QString::number(clientModel->getNumConnections()) + " (";
852  connections += tr("In:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_IN)) + " / ";
853  connections += tr("Out:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_OUT)) + ")";
854 
855  if(!clientModel->getNetworkActive()) {
856  connections += " (" + tr("Network activity disabled") + ")";
857  }
858 
859  ui->numberOfConnections->setText(connections);
860 }
861 
863 {
864  if (!clientModel)
865  return;
866 
868 }
869 
870 void RPCConsole::setNetworkActive(bool networkActive)
871 {
873 }
874 
875 void RPCConsole::setNumBlocks(int count, const QDateTime& blockDate, double nVerificationProgress, bool headers)
876 {
877  if (!headers) {
878  ui->numberOfBlocks->setText(QString::number(count));
879  ui->lastBlockTime->setText(blockDate.toString());
880  }
881 }
882 
883 void RPCConsole::setMempoolSize(long numberOfTxs, size_t dynUsage)
884 {
885  ui->mempoolNumberTxs->setText(QString::number(numberOfTxs));
886 
887  if (dynUsage < 1000000)
888  ui->mempoolSize->setText(QString::number(dynUsage/1000.0, 'f', 2) + " KB");
889  else
890  ui->mempoolSize->setText(QString::number(dynUsage/1000000.0, 'f', 2) + " MB");
891 }
892 
894 {
895  QString cmd = ui->lineEdit->text();
896 
897  if(!cmd.isEmpty())
898  {
899  std::string strFilteredCmd;
900  try {
901  std::string dummy;
902  if (!RPCParseCommandLine(dummy, cmd.toStdString(), false, &strFilteredCmd)) {
903  // Failed to parse command, so we cannot even filter it for the history
904  throw std::runtime_error("Invalid command line");
905  }
906  } catch (const std::exception& e) {
907  QMessageBox::critical(this, "Error", QString("Error: ") + QString::fromStdString(e.what()));
908  return;
909  }
910 
911  ui->lineEdit->clear();
912 
913  cmdBeforeBrowsing = QString();
914 
915  message(CMD_REQUEST, QString::fromStdString(strFilteredCmd));
916  Q_EMIT cmdRequest(cmd);
917 
918  cmd = QString::fromStdString(strFilteredCmd);
919 
920  // Remove command, if already in history
921  history.removeOne(cmd);
922  // Append command to history
923  history.append(cmd);
924  // Enforce maximum history size
925  while(history.size() > CONSOLE_HISTORY)
926  history.removeFirst();
927  // Set pointer to end of history
928  historyPtr = history.size();
929 
930  // Scroll console view to end
931  scrollToEnd();
932  }
933 }
934 
936 {
937  // store current text when start browsing through the history
938  if (historyPtr == history.size()) {
939  cmdBeforeBrowsing = ui->lineEdit->text();
940  }
941 
942  historyPtr += offset;
943  if(historyPtr < 0)
944  historyPtr = 0;
945  if(historyPtr > history.size())
946  historyPtr = history.size();
947  QString cmd;
948  if(historyPtr < history.size())
949  cmd = history.at(historyPtr);
950  else if (!cmdBeforeBrowsing.isNull()) {
951  cmd = cmdBeforeBrowsing;
952  }
953  ui->lineEdit->setText(cmd);
954 }
955 
957 {
958  RPCExecutor *executor = new RPCExecutor();
959  executor->moveToThread(&thread);
960 
961  // Replies from executor object must go to this object
962  connect(executor, SIGNAL(reply(int,QString)), this, SLOT(message(int,QString)));
963  // Requests from this object must go to executor
964  connect(this, SIGNAL(cmdRequest(QString)), executor, SLOT(request(QString)));
965 
966  // On stopExecutor signal
967  // - quit the Qt event loop in the execution thread
968  connect(this, SIGNAL(stopExecutor()), &thread, SLOT(quit()));
969  // - queue executor for deletion (in execution thread)
970  connect(&thread, SIGNAL(finished()), executor, SLOT(deleteLater()), Qt::DirectConnection);
971 
972  // Default implementation of QThread::run() simply spins up an event loop in the thread,
973  // which is what we want.
974  thread.start();
975 }
976 
978 {
979  if (ui->tabWidget->widget(index) == ui->tab_console)
980  ui->lineEdit->setFocus();
981  else if (ui->tabWidget->widget(index) != ui->tab_peers)
983 }
984 
986 {
988 }
989 
991 {
992  QScrollBar *scrollbar = ui->messagesWidget->verticalScrollBar();
993  scrollbar->setValue(scrollbar->maximum());
994 }
995 
997 {
998  const int multiplier = 5; // each position on the slider represents 5 min
999  int mins = value * multiplier;
1000  setTrafficGraphRange(mins);
1001 }
1002 
1004 {
1005  ui->trafficGraph->setGraphRangeMins(mins);
1006  ui->lblGraphRange->setText(GUIUtil::formatDurationStr(mins * 60));
1007 }
1008 
1009 void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
1010 {
1011  ui->lblBytesIn->setText(GUIUtil::formatBytes(totalBytesIn));
1012  ui->lblBytesOut->setText(GUIUtil::formatBytes(totalBytesOut));
1013 }
1014 
1015 void RPCConsole::peerSelected(const QItemSelection &selected, const QItemSelection &deselected)
1016 {
1017  Q_UNUSED(deselected);
1018 
1019  if (!clientModel || !clientModel->getPeerTableModel() || selected.indexes().isEmpty())
1020  return;
1021 
1022  const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.indexes().first().row());
1023  if (stats)
1024  updateNodeDetail(stats);
1025 }
1026 
1028 {
1029  QModelIndexList selected = ui->peerWidget->selectionModel()->selectedIndexes();
1030  cachedNodeids.clear();
1031  for(int i = 0; i < selected.size(); i++)
1032  {
1033  const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(selected.at(i).row());
1034  cachedNodeids.append(stats->nodeStats.nodeid);
1035  }
1036 }
1037 
1039 {
1041  return;
1042 
1043  const CNodeCombinedStats *stats = nullptr;
1044  bool fUnselect = false;
1045  bool fReselect = false;
1046 
1047  if (cachedNodeids.empty()) // no node selected yet
1048  return;
1049 
1050  // find the currently selected row
1051  int selectedRow = -1;
1052  QModelIndexList selectedModelIndex = ui->peerWidget->selectionModel()->selectedIndexes();
1053  if (!selectedModelIndex.isEmpty()) {
1054  selectedRow = selectedModelIndex.first().row();
1055  }
1056 
1057  // check if our detail node has a row in the table (it may not necessarily
1058  // be at selectedRow since its position can change after a layout change)
1059  int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeids.first());
1060 
1061  if (detailNodeRow < 0)
1062  {
1063  // detail node disappeared from table (node disconnected)
1064  fUnselect = true;
1065  }
1066  else
1067  {
1068  if (detailNodeRow != selectedRow)
1069  {
1070  // detail node moved position
1071  fUnselect = true;
1072  fReselect = true;
1073  }
1074 
1075  // get fresh stats on the detail node.
1076  stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
1077  }
1078 
1079  if (fUnselect && selectedRow >= 0) {
1081  }
1082 
1083  if (fReselect)
1084  {
1085  for(int i = 0; i < cachedNodeids.size(); i++)
1086  {
1087  ui->peerWidget->selectRow(clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeids.at(i)));
1088  }
1089  }
1090 
1091  if (stats)
1092  updateNodeDetail(stats);
1093 }
1094 
1096 {
1097  // update the detail ui with latest node information
1098  QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName) + " ");
1099  peerAddrDetails += tr("(node id: %1)").arg(QString::number(stats->nodeStats.nodeid));
1100  if (!stats->nodeStats.addrLocal.empty())
1101  peerAddrDetails += "<br />" + tr("via %1").arg(QString::fromStdString(stats->nodeStats.addrLocal));
1102  ui->peerHeading->setText(peerAddrDetails);
1103  ui->peerServices->setText(GUIUtil::formatServicesStr(stats->nodeStats.nServices));
1104  ui->peerLastSend->setText(stats->nodeStats.nLastSend ? GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nLastSend) : tr("never"));
1105  ui->peerLastRecv->setText(stats->nodeStats.nLastRecv ? GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nLastRecv) : tr("never"));
1106  ui->peerBytesSent->setText(GUIUtil::formatBytes(stats->nodeStats.nSendBytes));
1107  ui->peerBytesRecv->setText(GUIUtil::formatBytes(stats->nodeStats.nRecvBytes));
1108  ui->peerConnTime->setText(GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nTimeConnected));
1109  ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingTime));
1110  ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingWait));
1111  ui->peerMinPing->setText(GUIUtil::formatPingTime(stats->nodeStats.dMinPing));
1112  ui->timeoffset->setText(GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset));
1113  ui->peerVersion->setText(QString("%1").arg(QString::number(stats->nodeStats.nVersion)));
1114  ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer));
1115  ui->peerDirection->setText(stats->nodeStats.fInbound ? tr("Inbound") : tr("Outbound"));
1116  ui->peerHeight->setText(QString("%1").arg(QString::number(stats->nodeStats.nStartingHeight)));
1117  ui->peerWhitelisted->setText(stats->nodeStats.fWhitelisted ? tr("Yes") : tr("No"));
1118 
1119  // This check fails for example if the lock was busy and
1120  // nodeStateStats couldn't be fetched.
1121  if (stats->fNodeStateStatsAvailable) {
1122  // Ban score is init to 0
1123  ui->peerBanScore->setText(QString("%1").arg(stats->nodeStateStats.nMisbehavior));
1124 
1125  // Sync height is init to -1
1126  if (stats->nodeStateStats.nSyncHeight > -1)
1127  ui->peerSyncHeight->setText(QString("%1").arg(stats->nodeStateStats.nSyncHeight));
1128  else
1129  ui->peerSyncHeight->setText(tr("Unknown"));
1130 
1131  // Common height is init to -1
1132  if (stats->nodeStateStats.nCommonHeight > -1)
1133  ui->peerCommonHeight->setText(QString("%1").arg(stats->nodeStateStats.nCommonHeight));
1134  else
1135  ui->peerCommonHeight->setText(tr("Unknown"));
1136  }
1137 
1138  ui->detailWidget->show();
1139 }
1140 
1141 void RPCConsole::resizeEvent(QResizeEvent *event)
1142 {
1143  QWidget::resizeEvent(event);
1144 }
1145 
1146 void RPCConsole::showEvent(QShowEvent *event)
1147 {
1148  QWidget::showEvent(event);
1149 
1151  return;
1152 
1153  // start PeerTableModel auto refresh
1155 }
1156 
1157 void RPCConsole::hideEvent(QHideEvent *event)
1158 {
1159  QWidget::hideEvent(event);
1160 
1162  return;
1163 
1164  // stop PeerTableModel auto refresh
1166 }
1167 
1168 void RPCConsole::showPeersTableContextMenu(const QPoint& point)
1169 {
1170  QModelIndex index = ui->peerWidget->indexAt(point);
1171  if (index.isValid())
1172  peersTableContextMenu->exec(QCursor::pos());
1173 }
1174 
1175 void RPCConsole::showBanTableContextMenu(const QPoint& point)
1176 {
1177  QModelIndex index = ui->banlistWidget->indexAt(point);
1178  if (index.isValid())
1179  banTableContextMenu->exec(QCursor::pos());
1180 }
1181 
1183 {
1184  if(!g_connman)
1185  return;
1186 
1187  // Get selected peer addresses
1188  QList<QModelIndex> nodes = GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId);
1189  for(int i = 0; i < nodes.count(); i++)
1190  {
1191  // Get currently selected peer address
1192  NodeId id = nodes.at(i).data().toLongLong();
1193  // Find the node, disconnect it and clear the selected node
1194  if(g_connman->DisconnectNode(id))
1196  }
1197 }
1198 
1200 {
1201  if (!clientModel || !g_connman)
1202  return;
1203 
1204  // Get selected peer addresses
1205  QList<QModelIndex> nodes = GUIUtil::getEntryData(ui->peerWidget, PeerTableModel::NetNodeId);
1206  for(int i = 0; i < nodes.count(); i++)
1207  {
1208  // Get currently selected peer address
1209  NodeId id = nodes.at(i).data().toLongLong();
1210 
1211  // Get currently selected peer address
1212  int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(id);
1213  if(detailNodeRow < 0)
1214  return;
1215 
1216  // Find possible nodes, ban it and clear the selected node
1217  const CNodeCombinedStats *stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
1218  if(stats) {
1219  g_connman->Ban(stats->nodeStats.addr, BanReasonManuallyAdded, bantime);
1220  }
1221  }
1224 }
1225 
1227 {
1228  if (!clientModel)
1229  return;
1230 
1231  // Get selected ban addresses
1232  QList<QModelIndex> nodes = GUIUtil::getEntryData(ui->banlistWidget, BanTableModel::Address);
1233  for(int i = 0; i < nodes.count(); i++)
1234  {
1235  // Get currently selected ban address
1236  QString strNode = nodes.at(i).data().toString();
1237  CSubNet possibleSubnet;
1238 
1239  LookupSubNet(strNode.toStdString().c_str(), possibleSubnet);
1240  if (possibleSubnet.IsValid() && g_connman)
1241  {
1242  g_connman->Unban(possibleSubnet);
1244  }
1245  }
1246 }
1247 
1249 {
1250  ui->peerWidget->selectionModel()->clearSelection();
1251  cachedNodeids.clear();
1252  ui->detailWidget->hide();
1253  ui->peerHeading->setText(tr("Select a peer to view detailed information."));
1254 }
1255 
1257 {
1258  if (!clientModel)
1259  return;
1260 
1261  bool visible = clientModel->getBanTableModel()->shouldShow();
1262  ui->banlistWidget->setVisible(visible);
1263  ui->banHeading->setVisible(visible);
1264 }
1265 
1267 {
1268  ui->tabWidget->setCurrentIndex(tabType);
1269 }
void openDebugLogfile()
Definition: guiutil.cpp:488
QString formatClientStartupTime() const
int getRowByNodeId(NodeId nodeid)
const char * Name()
Implementation name.
Definition: rpcconsole.cpp:128
RPCTimerBase * NewTimer(std::function< void(void)> &func, int64_t millis)
Factory function for timers.
Definition: rpcconsole.cpp:129
bool isObject() const
Definition: univalue.h:86
int nStartingHeight
Definition: net.h:531
QString formatSubVersion() const
Local Raven RPC console.
Definition: rpcconsole.h:32
RPC timer "driver".
Definition: server.h:101
void keyPressEvent(QKeyEvent *)
Definition: rpcconsole.cpp:825
QString cmdBeforeBrowsing
Definition: rpcconsole.h:157
QFont fixedPitchFont()
Definition: guiutil.cpp:168
CNodeStateStats nodeStateStats
bool getNetworkActive() const
Return true if network activity in core is enabled.
QList< QModelIndex > getEntryData(QAbstractItemView *view, int column)
Return a field of the currently selected entry as a QString.
Definition: guiutil.cpp:368
int64_t nTimeOffset
Definition: net.h:525
void showEvent(QShowEvent *event)
void on_lineEdit_returnPressed()
Definition: rpcconsole.cpp:893
void message(int category, const QString &message, bool html=false)
Append the message to the message widget.
Definition: rpcconsole.cpp:833
static bool RPCExecuteCommandLine(std::string &strResult, const std::string &strCommand, std::string *const pstrFilteredOut=nullptr)
Definition: rpcconsole.h:41
void showPeersTableContextMenu(const QPoint &point)
Show custom context menu on Peers tab.
RPCConsole(const PlatformStyle *platformStyle, QWidget *parent)
Definition: rpcconsole.cpp:429
QStringList history
Definition: rpcconsole.h:155
QThread thread
Definition: rpcconsole.h:165
ServiceFlags nServices
Definition: net.h:520
void setNetworkActive(bool networkActive)
Set network state shown in the UI.
Definition: rpcconsole.cpp:870
void scrollToEnd()
Scroll console view to end.
Definition: rpcconsole.cpp:990
const QString REINDEX("-reindex")
QString formatBytes(uint64_t bytes)
Definition: guiutil.cpp:1066
std::string write(unsigned int prettyIndent=0, unsigned int indentLevel=0) const
QString formatTimeOffset(int64_t nTimeOffset)
Definition: guiutil.cpp:1024
std::string cleanSubVer
Definition: net.h:528
void clearSelectedNode()
clear the selected node
std::vector< CWalletRef > vpwallets
Definition: wallet.cpp:44
const std::string & get_str() const
QIcon SingleColorIcon(const QString &filename) const
Colorize an icon (given filename) with the icon color.
int64_t nTimeConnected
Definition: net.h:524
bool isStr() const
Definition: univalue.h:83
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:336
void fontSmaller()
Definition: rpcconsole.cpp:696
quint64 getTotalBytesSent() const
PeerTableModel * getPeerTableModel()
void handleRestart(QStringList args)
Get restart command-line parameters and handle restart.
void disconnectSelectedNode()
Disconnect a selected node on the Peers tab.
CNodeStats nodeStats
#define PACKAGE_NAME
Definition: raven-config.h:350
void on_tabWidget_currentChanged(int index)
Definition: rpcconsole.cpp:977
void updateNodeDetail(const CNodeCombinedStats *stats)
show detailed information on ui about selected node
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
Unset factory function for timers.
Definition: server.cpp:544
const UniValue & find_value(const UniValue &obj, const std::string &name)
Definition: univalue.cpp:236
UniValue RPCConvertValues(const std::string &strMethod, const std::vector< std::string > &strParams)
Convert positional arguments to command-specific RPC representation.
Definition: client.cpp:246
void setClientModel(ClientModel *model)
Definition: rpcconsole.cpp:547
void resizeEvent(QResizeEvent *event)
UniValue execute(const JSONRPCRequest &request) const
Execute a method.
Definition: server.cpp:480
const struct @18 ICON_MAPPING[]
std::string strMethod
Definition: server.h:44
const char * url
Definition: rpcconsole.cpp:65
void reply(int category, const QString &command)
void walletRescan()
Wallet repair options.
Definition: rpcconsole.cpp:727
QMenu * peersTableContextMenu
Definition: rpcconsole.h:161
CRPCTable tableRPC
Definition: server.cpp:567
int nVersion
Definition: net.h:527
const char * source
Definition: rpcconsole.cpp:66
void browseHistory(int offset)
Go forward or back in history.
Definition: rpcconsole.cpp:935
bool push_back(const UniValue &val)
Definition: univalue.cpp:110
int getNumConnections(unsigned int flags=CONNECTIONS_ALL) const
Return number of connections, default is in- and outbound (total)
Definition: clientmodel.cpp:57
double getVerificationProgress(const CBlockIndex *tip) const
int64_t GetSystemTimeInSeconds()
Definition: utiltime.cpp:56
Class for handling RPC timers (used for e.g.
Definition: rpcconsole.cpp:105
QString formatDurationStr(int secs)
Definition: guiutil.cpp:961
UniValue params
Definition: server.h:45
std::function< void(void)> func
Definition: rpcconsole.cpp:121
const int CONSOLE_HISTORY
Definition: rpcconsole.cpp:54
const QString RESCAN("-rescan")
quint64 getTotalBytesRecv() const
void buildParameterlist(QString arg)
Build parameter list for restart.
Definition: rpcconsole.cpp:757
void walletReindex()
Restart wallet with "-reindex".
Definition: rpcconsole.cpp:739
QtRPCTimerBase(std::function< void(void)> &_func, int64_t millis)
Definition: rpcconsole.cpp:109
void setTabFocus(enum TabTypes tabType)
set which tab has the focus (is visible)
void request(const QString &command)
Definition: rpcconsole.cpp:397
bool fInbound
Definition: net.h:529
BanTableModel * getBanTableModel()
uint64_t nRecvBytes
Definition: net.h:534
int historyPtr
Definition: rpcconsole.h:156
void peerLayoutChanged()
Handle updated peer information.
RPCTimerInterface * rpcTimerInterface
Definition: rpcconsole.h:160
double dPingTime
Definition: net.h:537
std::string addrName
Definition: net.h:526
static bool RPCParseCommandLine(std::string &strResult, const std::string &strCommand, bool fExecute, std::string *const pstrFilteredOut=nullptr)
Split shell command line into a list of arguments and optionally execute the command(s).
Definition: rpcconsole.cpp:157
void updateNetworkState()
Update UI with latest network info from model.
Definition: rpcconsole.cpp:849
int64_t NodeId
Definition: net.h:93
const CNodeCombinedStats * getNodeStats(int idx)
const QString ZAPTXES1("-zapwallettxes=1")
int get_int() const
uint64_t nSendBytes
Definition: net.h:532
void on_openDebugLogfileButton_clicked()
open the debug.log from the current datadir
Definition: rpcconsole.cpp:985
Model for Raven network client.
Definition: clientmodel.h:39
void unbanSelectedNode()
Unban a selected node on the Bans tab.
void hideEvent(QHideEvent *event)
ClientModel * clientModel
Definition: rpcconsole.h:154
QString formatPingTime(double dPingTime)
Definition: guiutil.cpp:1019
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
Set the factory function for timer, but only, if unset.
Definition: server.cpp:533
virtual bool eventFilter(QObject *obj, QEvent *event)
Definition: rpcconsole.cpp:503
QMenu * banTableContextMenu
Definition: rpcconsole.h:162
bool LookupSubNet(const char *pszName, CSubNet &ret)
Definition: netbase.cpp:615
void setTrafficGraphRange(int mins)
void clear(bool clearHistory=true)
Definition: rpcconsole.cpp:775
QDateTime getLastBlockDate() const
void showOrHideBanTableIfRequired()
Hides ban table if no bans are present.
void fontBigger()
Definition: rpcconsole.cpp:691
void updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
update traffic statistics
bool IsValid() const
Definition: netaddress.cpp:722
ArgsManager gArgs
Definition: util.cpp:94
QList< NodeId > cachedNodeids
Definition: rpcconsole.h:158
void walletZaptxes1()
Restart wallet with "-zapwallettxes=1".
Definition: rpcconsole.cpp:733
void setMempoolSize(long numberOfTxs, size_t dynUsage)
Set size (number of transactions and memory usage) of the mempool in the UI.
Definition: rpcconsole.cpp:883
void setFontSize(int newSize)
Definition: rpcconsole.cpp:701
void setNumConnections(int count)
Set number of connections shown in the UI.
Definition: rpcconsole.cpp:862
void startExecutor()
Definition: rpcconsole.cpp:956
QImage SingleColorImage(const QString &filename) const
Colorize an image (given filename) with the icon color.
const CChainParams & Params()
Return the currently selected parameters.
void peerLayoutAboutToChange()
Handle selection caching before update.
QString formatServicesStr(quint64 mask)
Definition: guiutil.cpp:981
std::string addrLocal
Definition: net.h:541
std::string GetArg(const std::string &strArg, const std::string &strDefault) const
Return string argument or default value.
Definition: util.cpp:454
void on_sldGraphRange_valueChanged(int value)
change the time range of the network traffic graph
Definition: rpcconsole.cpp:996
std::string URI
Definition: server.h:47
void banSelectedNode(int bantime)
Ban a selected node on the Peers tab.
double dMinPing
Definition: net.h:539
Opaque base class for timers returned by NewTimerFunc.
Definition: server.h:92
const int INITIAL_TRAFFIC_GRAPH_MINS
Definition: rpcconsole.cpp:55
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:81
const char fontSizeSettingsKey[]
Definition: rpcconsole.cpp:57
void peerSelected(const QItemSelection &selected, const QItemSelection &deselected)
Handle selection of peer in peers list.
int consoleFontSize
Definition: rpcconsole.h:163
const fs::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:572
const QSize FONT_RANGE(4, 40)
QString dataDir() const
void clear()
Definition: univalue.cpp:17
int getNumBlocks() const
Definition: clientmodel.cpp:73
bool fWhitelisted
Definition: net.h:536
Ui::RPCConsole * ui
Definition: rpcconsole.h:153
std::vector< std::string > listCommands() const
Returns a list of registered commands.
Definition: server.cpp:511
QCompleter * autoCompleter
Definition: rpcconsole.h:164
void stopExecutor()
double dPingWait
Definition: net.h:538
void cmdRequest(const QString &command)
bool isArray() const
Definition: univalue.h:85
bool getImagesOnButtons() const
Definition: platformstyle.h:24
int64_t nLastSend
Definition: net.h:522
const PlatformStyle * platformStyle
Definition: rpcconsole.h:159
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:875
int atoi(const std::string &str)
NodeId nodeid
Definition: net.h:519
void showBanTableContextMenu(const QPoint &point)
Show custom context menu on Bans tab.
int64_t nLastRecv
Definition: net.h:523
CAddress addr
Definition: net.h:543
QString formatFullVersion() const