PIVX Core  5.6.99
P2P Digital Currency
rpcconsole.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2014 The Bitcoin developers
2 // Copyright (c) 2014-2015 The Dash developers
3 // Copyright (c) 2015-2021 The PIVX Core developers
4 // Distributed under the MIT/X11 software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include "rpcconsole.h"
8 #include "ui_rpcconsole.h"
9 
10 #include "bantablemodel.h"
11 #include "clientmodel.h"
12 #include "peertablemodel.h"
13 #include "qt/rpcexecutor.h"
14 #include "walletmodel.h"
15 
16 #include "chainparams.h"
17 #include "netbase.h"
18 #include "util/system.h"
19 
20 #ifdef ENABLE_WALLET
21 #include <db_cxx.h>
22 #endif
23 
24 #include <QDir>
25 #include <QKeyEvent>
26 #include <QMenu>
27 #include <QScrollBar>
28 #include <QThread>
29 #include <QTime>
30 #include <QStringList>
31 
32 // TODO: add a scrollback limit, as there is currently none
33 // TODO: make it possible to filter out categories (esp debug messages when implemented)
34 // TODO: receive errors and debug messages through ClientModel
35 
36 const int CONSOLE_HISTORY = 50;
37 const QSize ICON_SIZE(24, 24);
38 
40 
41 // Repair parameters
42 const QString SALVAGEWALLET("-salvagewallet");
43 const QString RESCAN("-rescan");
44 const QString ZAPTXES1("-zapwallettxes=1");
45 const QString ZAPTXES2("-zapwallettxes=2");
46 const QString UPGRADEWALLET("-upgradewallet");
47 const QString REINDEX("-reindex");
48 const QString RESYNC("-resync");
49 
50 const struct {
51  const char* url;
52  const char* source;
53 } ICON_MAPPING[] = {
54  {"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 RPCConsole::RPCConsole(QWidget* parent) : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint | Qt::WindowCloseButtonHint),
61  ui(new Ui::RPCConsole),
62  clientModel(nullptr),
63  walletModel(nullptr),
64  historyPtr(0),
65  cachedNodeid(-1),
66  peersTableContextMenu(nullptr),
67  banTableContextMenu(nullptr)
68 {
69  ui->setupUi(this);
70  GUIUtil::restoreWindowGeometry("nRPCConsoleWindow", this->size(), this);
71 
72 #ifndef Q_OS_MAC
73  ui->openDebugLogfileButton->setIcon(QIcon(":/icons/export"));
74 #endif
75 
76  // Install event filter for up and down arrow
77  ui->lineEdit->installEventFilter(this);
78  ui->messagesWidget->installEventFilter(this);
79 
80  connect(ui->clearButton, &QPushButton::clicked, this, &RPCConsole::clear);
81  connect(ui->btnClearTrafficGraph, &QPushButton::clicked, ui->trafficGraph, &TrafficGraphWidget::clear);
82 
83  // Wallet Repair Buttons
84  connect(ui->btn_salvagewallet, &QPushButton::clicked, this, &RPCConsole::walletSalvage);
85  connect(ui->btn_rescan, &QPushButton::clicked, this, &RPCConsole::walletRescan);
86  connect(ui->btn_zapwallettxes1, &QPushButton::clicked, this, &RPCConsole::walletZaptxes1);
87  connect(ui->btn_zapwallettxes2, &QPushButton::clicked, this, &RPCConsole::walletZaptxes2);
88  connect(ui->btn_upgradewallet, &QPushButton::clicked, this, &RPCConsole::walletUpgrade);
89  connect(ui->btn_reindex, &QPushButton::clicked, this, &RPCConsole::walletReindex);
90  connect(ui->btn_resync, &QPushButton::clicked, this, &RPCConsole::walletResync);
91 
92  // set library version labels
93 #ifdef ENABLE_WALLET
94  ui->berkeleyDBVersion->setText(DbEnv::version(0, 0, 0));
95 #else
96 
97  ui->label_berkeleyDBVersion->hide();
98  ui->berkeleyDBVersion->hide();
99 #endif
100  // Register RPC timer interface
102  // avoid accidentally overwriting an existing, non QTThread
103  // based timer interface
105 
106  startExecutor();
108 
109  ui->peerHeading->setText(tr("Select a peer to view detailed information."));
110 
111  clear();
112 }
113 
115 {
116  GUIUtil::saveWindowGeometry("nRPCConsoleWindow", this);
117  Q_EMIT stopExecutor();
119  delete rpcTimerInterface;
120  delete ui;
121 }
122 
123 bool RPCConsole::eventFilter(QObject* obj, QEvent* event)
124 {
125  if (event->type() == QEvent::KeyPress) // Special key handling
126  {
127  QKeyEvent* keyevt = static_cast<QKeyEvent*>(event);
128  int key = keyevt->key();
129  Qt::KeyboardModifiers mod = keyevt->modifiers();
130  switch (key) {
131  case Qt::Key_Up:
132  if (obj == ui->lineEdit) {
133  browseHistory(-1);
134  return true;
135  }
136  break;
137  case Qt::Key_Down:
138  if (obj == ui->lineEdit) {
139  browseHistory(1);
140  return true;
141  }
142  break;
143  case Qt::Key_PageUp: /* pass paging keys to messages widget */
144  case Qt::Key_PageDown:
145  if (obj == ui->lineEdit) {
146  QApplication::postEvent(ui->messagesWidget, new QKeyEvent(*keyevt));
147  return true;
148  }
149  break;
150  case Qt::Key_Return:
151  case Qt::Key_Enter:
152  // forward these events to lineEdit
153  if(obj == autoCompleter->popup()) {
154  QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
155  return true;
156  }
157  break;
158  default:
159  // Typing in messages widget brings focus to line edit, and redirects key there
160  // Exclude most combinations and keys that emit no text, except paste shortcuts
161  if (obj == ui->messagesWidget && ((!mod && !keyevt->text().isEmpty() && key != Qt::Key_Tab) ||
162  ((mod & Qt::ControlModifier) && key == Qt::Key_V) ||
163  ((mod & Qt::ShiftModifier) && key == Qt::Key_Insert))) {
164  ui->lineEdit->setFocus();
165  QApplication::postEvent(ui->lineEdit, new QKeyEvent(*keyevt));
166  return true;
167  }
168  }
169  }
170  return QDialog::eventFilter(obj, event);
171 }
172 
174 {
175  clientModel = model;
176  ui->trafficGraph->setClientModel(model);
178  // Keep up to date with client
179  int num_connections = model->getNumConnections();
180  setNumConnections(num_connections);
182 
183  setNumBlocks(model->getNumBlocks());
185 
187 
188  updateNetworkState(num_connections);
190 
193 
194  // set up peer table
195  ui->peerWidget->setModel(model->getPeerTableModel());
196  ui->peerWidget->verticalHeader()->hide();
197  ui->peerWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
198  ui->peerWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
199  ui->peerWidget->setSelectionMode(QAbstractItemView::SingleSelection);
200  ui->peerWidget->setContextMenuPolicy(Qt::CustomContextMenu);
201  ui->peerWidget->setColumnWidth(PeerTableModel::Address, ADDRESS_COLUMN_WIDTH);
202  ui->peerWidget->setColumnWidth(PeerTableModel::Subversion, SUBVERSION_COLUMN_WIDTH);
203  ui->peerWidget->setColumnWidth(PeerTableModel::Ping, PING_COLUMN_WIDTH);
204  ui->peerWidget->horizontalHeader()->setStretchLastSection(true);
205 
206  // create peer table context menu actions
207  QAction* disconnectAction = new QAction(tr("&Disconnect Node"), this);
208  QAction* banAction1h = new QAction(tr("Ban Node for") + " " + tr("1 &hour"), this);
209  QAction* banAction24h = new QAction(tr("Ban Node for") + " " + tr("1 &day"), this);
210  QAction* banAction7d = new QAction(tr("Ban Node for") + " " + tr("1 &week"), this);
211  QAction* banAction365d = new QAction(tr("Ban Node for") + " " + tr("1 &year"), this);
212 
213  // create peer table context menu
214  peersTableContextMenu = new QMenu();
215  peersTableContextMenu->addAction(disconnectAction);
216  peersTableContextMenu->addAction(banAction1h);
217  peersTableContextMenu->addAction(banAction24h);
218  peersTableContextMenu->addAction(banAction7d);
219  peersTableContextMenu->addAction(banAction365d);
220 
221  connect(banAction1h, &QAction::triggered, [this] { banSelectedNode(60 * 60); });
222  connect(banAction24h, &QAction::triggered, [this] { banSelectedNode(60 * 60 * 24); });
223  connect(banAction7d, &QAction::triggered, [this] { banSelectedNode(60 * 60 * 24 * 7); });
224  connect(banAction365d, &QAction::triggered, [this] { banSelectedNode(60 * 60 * 24 * 365); });
225 
226  // peer table context menu signals
227  connect(ui->peerWidget, &QTableView::customContextMenuRequested, this, &RPCConsole::showPeersTableContextMenu);
228  connect(disconnectAction, &QAction::triggered, this, &RPCConsole::disconnectSelectedNode);
229 
230  // peer table signal handling - update peer details when selecting new node
231  connect(ui->peerWidget->selectionModel(), &QItemSelectionModel::selectionChanged, this, &RPCConsole::peerSelected);
232  // peer table signal handling - update peer details when new nodes are added to the model
233  connect(model->getPeerTableModel(), &PeerTableModel::layoutChanged, this, &RPCConsole::peerLayoutChanged);
234 
235  // set up ban table
236  ui->banlistWidget->setModel(model->getBanTableModel());
237  ui->banlistWidget->verticalHeader()->hide();
238  ui->banlistWidget->setEditTriggers(QAbstractItemView::NoEditTriggers);
239  ui->banlistWidget->setSelectionBehavior(QAbstractItemView::SelectRows);
240  ui->banlistWidget->setSelectionMode(QAbstractItemView::SingleSelection);
241  ui->banlistWidget->setContextMenuPolicy(Qt::CustomContextMenu);
242  ui->banlistWidget->setColumnWidth(BanTableModel::Address, BANSUBNET_COLUMN_WIDTH);
243  ui->banlistWidget->setColumnWidth(BanTableModel::Bantime, BANTIME_COLUMN_WIDTH);
244  ui->banlistWidget->horizontalHeader()->setStretchLastSection(true);
245 
246  // create ban table context menu action
247  QAction* unbanAction = new QAction(tr("&Unban Node"), this);
248 
249  // create ban table context menu
250  banTableContextMenu = new QMenu();
251  banTableContextMenu->addAction(unbanAction);
252 
253  // ban table context menu signals
254  connect(ui->banlistWidget, &QTableView::customContextMenuRequested, this, &RPCConsole::showBanTableContextMenu);
255  connect(unbanAction, &QAction::triggered, this, &RPCConsole::unbanSelectedNode);
256 
257  // ban table signal handling - clear peer details when clicking a peer in the ban table
258  connect(ui->banlistWidget, &QTableView::clicked, this, &RPCConsole::clearSelectedNode);
259  // ban table signal handling - ensure ban table is shown or hidden (if empty)
260  connect(model->getBanTableModel(), &BanTableModel::layoutChanged, this, &RPCConsole::showOrHideBanTableIfRequired);
262 
263  // Provide initial values
264  ui->clientVersion->setText(model->formatFullVersion());
265  ui->clientName->setText(model->clientName());
266  ui->dataDir->setText(model->dataDir());
267  ui->startupTime->setText(model->formatClientStartupTime());
268  ui->networkName->setText(QString::fromStdString(Params().NetworkIDString()));
269 
270  //Setup autocomplete and attach it
271  QStringList wordList;
272  std::vector<std::string> commandList = tableRPC.listCommands();
273  for (size_t i = 0; i < commandList.size(); ++i)
274  {
275  wordList << commandList[i].c_str();
276  wordList << ("help " + commandList[i]).c_str();
277  }
278 
279  wordList << "help-console";
280  wordList.sort();
281  autoCompleter = new QCompleter(wordList, this);
282  autoCompleter->setModelSorting(QCompleter::CaseSensitivelySortedModel);
283  ui->lineEdit->setCompleter(autoCompleter);
284 
285  // clear the lineEdit after activating from QCompleter
286  autoCompleter->popup()->installEventFilter(this);
287  }
288 }
289 
291 {
292  walletModel = model;
293  if (walletModel) {
294  ui->wallet_path->setText(walletModel->getWalletPath());
295  }
296 }
297 
300 {
302 }
303 
306 {
308 }
309 
312 {
314 }
315 
318 {
320 }
321 
324 {
326 }
327 
330 {
332 }
333 
336 {
337  QString resyncWarning = tr("This will delete your local blockchain folders and the wallet will synchronize the complete Blockchain from scratch.<br /><br />");
338  resyncWarning += tr("This needs quite some time and downloads a lot of data.<br /><br />");
339  resyncWarning += tr("Your transactions and funds will be visible again after the download has completed.<br /><br />");
340  resyncWarning += tr("Do you want to continue?.<br />");
341  QMessageBox::StandardButton retval = QMessageBox::question(this, tr("Confirm resync Blockchain"),
342  resyncWarning,
343  QMessageBox::Yes | QMessageBox::Cancel,
344  QMessageBox::Cancel);
345 
346  if (retval != QMessageBox::Yes) {
347  // Resync canceled
348  return;
349  }
350 
351  // Restart and resync
353 }
354 
357 {
358  // Get command-line arguments and remove the application name
359  QStringList args = QApplication::arguments();
360  args.removeFirst();
361 
362  // Remove existing repair-options
363  args.removeAll(SALVAGEWALLET);
364  args.removeAll(RESCAN);
365  args.removeAll(ZAPTXES1);
366  args.removeAll(ZAPTXES2);
367  args.removeAll(UPGRADEWALLET);
368  args.removeAll(REINDEX);
369 
370  // Append repair parameter to command line.
371  args.append(arg);
372 
373  // Send command-line arguments to BitcoinGUI::handleRestart()
374  Q_EMIT handleRestart(args);
375 }
376 
378 {
379  ui->messagesWidget->clear();
380  history.clear();
381  historyPtr = 0;
382  ui->lineEdit->clear();
383  ui->lineEdit->setFocus();
384 
385  // Add smoothly scaled icon images.
386  // (when using width/height on an img, Qt uses nearest instead of linear interpolation)
387  for (int i = 0; ICON_MAPPING[i].url; ++i) {
388  ui->messagesWidget->document()->addResource(
389  QTextDocument::ImageResource,
390  QUrl(ICON_MAPPING[i].url),
391  QImage(ICON_MAPPING[i].source).scaled(ICON_SIZE, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
392  }
393 
394  // Set default style sheet
395  ui->messagesWidget->document()->setDefaultStyleSheet(
396  "table { }"
397  "td.time { color: #808080; padding-top: 3px; } "
398  "td.message { font-family: Courier, Courier New, Lucida Console, monospace; font-size: 12px; } " // Todo: Remove fixed font-size
399  "td.cmd-request { color: #006060; } "
400  "td.cmd-error { color: red; } "
401  ".secwarning { color: red; }"
402  "b { color: #006060; } ");
403 
404 #ifdef Q_OS_MAC
405  QString clsKey = "(⌘)-L";
406 #else
407  QString clsKey = "Ctrl-L";
408 #endif
409 
410  message(RPCExecutor::CMD_REPLY, (tr("Welcome to the PIVX RPC console.") + "<br>" +
411  tr("Use up and down arrows to navigate history, and %1 to clear screen.").arg("<b>"+clsKey+"</b>") + "<br>" +
412  tr("Type %1 for an overview of available commands.").arg("<b>help</b>") + "<br>" +
413  tr("For more information on using this console type %1.").arg("<b>help-console</b>") +
414  "<br><span class=\"secwarning\"><br>" +
415  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.") +
416  "</span>"),
417  true);
418 }
419 
421 {
422  // Ignore escape keypress if this is not a separate window
423  if (windowType() != Qt::Widget)
424  QDialog::reject();
425 }
426 
427 void RPCConsole::message(int category, const QString& message, bool html)
428 {
429  QTime time = QTime::currentTime();
430  QString timeString = time.toString();
431  QString out;
432  out += "<table><tr><td class=\"time\" width=\"65\">" + timeString + "</td>";
433  out += "<td class=\"icon\" width=\"32\"><img src=\"" + RPCExecutor::categoryClass(category) + "\"></td>";
434  out += "<td class=\"message " + RPCExecutor::categoryClass(category) + "\" valign=\"middle\">";
435  if (html)
436  out += message;
437  else
438  out += GUIUtil::HtmlEscape(message, true);
439  out += "</td></tr></table>";
440  ui->messagesWidget->append(out);
441 }
442 
443 void RPCConsole::updateNetworkState(int numConnections)
444 {
445  bool netActivityState = clientModel->getNetworkActive();
446  QString connections;
447  if (!netActivityState && numConnections == 0) {
448  connections = tr("Network activity disabled");
449  } else {
450  connections = QString::number(numConnections) + " (";
451  connections += tr("In:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_IN)) + " / ";
452  connections += tr("Out:") + " " + QString::number(clientModel->getNumConnections(CONNECTIONS_OUT)) + ")";
453  if(!netActivityState) {
454  connections += " " + tr("Network activity disabled");
455  }
456  }
457  ui->numberOfConnections->setText(connections);
458 }
459 
461 {
462  if (!clientModel)
463  return;
464 
465  updateNetworkState(count);
466 }
467 
468 void RPCConsole::setNetworkActive(bool networkActive)
469 {
470  if (!clientModel) return;
472 }
473 
475 {
476  ui->numberOfBlocks->setText(QString::number(count));
477  if (clientModel) {
478  ui->lastBlockTime->setText(clientModel->getLastBlockDate().toString());
479  ui->lastBlockHash->setText(clientModel->getLastBlockHash());
480  }
481 }
482 
483 void RPCConsole::setMasternodeCount(const QString& strMasternodes)
484 {
485  ui->masternodeCount->setText(strMasternodes);
486 }
487 
489 {
490  QString cmd = ui->lineEdit->text();
491  ui->lineEdit->clear();
492 
493  if (!cmd.isEmpty()) {
495  Q_EMIT cmdRequest(cmd);
496  // Remove command, if already in history
497  history.removeOne(cmd);
498  // Append command to history
499  history.append(cmd);
500  // Enforce maximum history size
501  while (history.size() > CONSOLE_HISTORY)
502  history.removeFirst();
503  // Set pointer to end of history
504  historyPtr = history.size();
505  // Scroll console view to end
506  scrollToEnd();
507  }
508 }
509 
511 {
512  historyPtr += offset;
513  if (historyPtr < 0)
514  historyPtr = 0;
515  if (historyPtr > history.size())
516  historyPtr = history.size();
517  QString cmd;
518  if (historyPtr < history.size())
519  cmd = history.at(historyPtr);
520  ui->lineEdit->setText(cmd);
521 }
522 
524 {
525  QThread* thread = new QThread;
526  RPCExecutor* executor = new RPCExecutor();
527  executor->moveToThread(thread);
528 
529  // Replies from executor object must go to this object
530  connect(executor, &RPCExecutor::reply, this, static_cast<void (RPCConsole::*)(int, const QString&)>(&RPCConsole::message));
531  // Requests from this object must go to executor
532  connect(this, &RPCConsole::cmdRequest, executor, &RPCExecutor::request);
533 
534  // On stopExecutor signal
535  // - queue executor for deletion (in execution thread)
536  // - quit the Qt event loop in the execution thread
537  connect(this, &RPCConsole::stopExecutor, executor, &RPCExecutor::deleteLater);
538  connect(this, &RPCConsole::stopExecutor, thread, &QThread::quit);
539  // Queue the thread for deletion (in this thread) when it is finished
540  connect(thread, &QThread::finished, thread, &QThread::deleteLater);
541 
542  // Default implementation of QThread::run() simply spins up an event loop in the thread,
543  // which is what we want.
544  thread->start();
545 }
546 
548 {
549  if (ui->tabWidget->widget(index) == ui->tab_console) {
550  ui->lineEdit->setFocus();
551  } else if (ui->tabWidget->widget(index) != ui->tab_peers) {
553  }
554 }
555 
557 {
559 }
560 
562 {
563  QScrollBar* scrollbar = ui->messagesWidget->verticalScrollBar();
564  scrollbar->setValue(scrollbar->maximum());
565 }
566 
568 {
569  const int multiplier = 5; // each position on the slider represents 5 min
570  int mins = value * multiplier;
571  setTrafficGraphRange(mins);
572 }
573 
574 QString RPCConsole::FormatBytes(quint64 bytes)
575 {
576  if (bytes < 1024)
577  return QString(tr("%1 B")).arg(bytes);
578  if (bytes < 1024 * 1024)
579  return QString(tr("%1 KB")).arg(bytes / 1024);
580  if (bytes < 1024 * 1024 * 1024)
581  return QString(tr("%1 MB")).arg(bytes / 1024 / 1024);
582 
583  return QString(tr("%1 GB")).arg(bytes / 1024 / 1024 / 1024);
584 }
585 
587 {
588  ui->trafficGraph->setGraphRangeMins(mins);
589  ui->lblGraphRange->setText(GUIUtil::formatDurationStr(mins * 60));
590 }
591 
592 void RPCConsole::updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
593 {
594  ui->lblBytesIn->setText(FormatBytes(totalBytesIn));
595  ui->lblBytesOut->setText(FormatBytes(totalBytesOut));
596 }
597 
599 {
600  ui->tabWidget->setCurrentIndex(0);
601  show();
602 }
603 
605 {
606  ui->tabWidget->setCurrentIndex(1);
607  show();
608 }
609 
611 {
612  ui->tabWidget->setCurrentIndex(2);
613  show();
614 }
615 
617 {
618  ui->tabWidget->setCurrentIndex(3);
619  show();
620 }
621 
623 {
624  ui->tabWidget->setCurrentIndex(4);
625  show();
626 }
627 
629 {
631 }
632 
634 {
636 }
637 
638 void RPCConsole::peerSelected(const QItemSelection& selected, const QItemSelection& deselected)
639 {
640  Q_UNUSED(deselected);
641 
642  if (!clientModel || !clientModel->getPeerTableModel() || selected.indexes().isEmpty())
643  return;
644 
645  const CNodeCombinedStats* stats = clientModel->getPeerTableModel()->getNodeStats(selected.indexes().first().row());
646  if (stats)
647  updateNodeDetail(stats);
648 }
649 
651 {
653  return;
654 
655  const CNodeCombinedStats* stats = nullptr;
656  bool fUnselect = false;
657  bool fReselect = false;
658 
659  if (cachedNodeid == -1) // no node selected yet
660  return;
661 
662  // find the currently selected row
663  int selectedRow = -1;
664  QModelIndexList selectedModelIndex = ui->peerWidget->selectionModel()->selectedIndexes();
665  if (!selectedModelIndex.isEmpty()) {
666  selectedRow = selectedModelIndex.first().row();
667  }
668 
669  // check if our detail node has a row in the table (it may not necessarily
670  // be at selectedRow since its position can change after a layout change)
671  int detailNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeid);
672 
673  if (detailNodeRow < 0) {
674  // detail node disappeared from table (node disconnected)
675  fUnselect = true;
676  } else {
677  if (detailNodeRow != selectedRow) {
678  // detail node moved position
679  fUnselect = true;
680  fReselect = true;
681  }
682 
683  // get fresh stats on the detail node.
684  stats = clientModel->getPeerTableModel()->getNodeStats(detailNodeRow);
685  }
686 
687  if (fUnselect && selectedRow >= 0) {
689  }
690 
691  if (fReselect) {
692  ui->peerWidget->selectRow(detailNodeRow);
693  }
694 
695  if (stats)
696  updateNodeDetail(stats);
697 }
698 
700 {
701  // Update cached nodeid
702  cachedNodeid = stats->nodeStats.nodeid;
703 
704  // update the detail ui with latest node information
705  QString peerAddrDetails(QString::fromStdString(stats->nodeStats.addrName) + " ");
706  peerAddrDetails += tr("(node id: %1)").arg(QString::number(stats->nodeStats.nodeid));
707  if (!stats->nodeStats.addrLocal.empty())
708  peerAddrDetails += "<br />" + tr("via %1").arg(QString::fromStdString(stats->nodeStats.addrLocal));
709  ui->peerHeading->setText(peerAddrDetails);
710  ui->peerServices->setText(GUIUtil::formatServicesStr(stats->nodeStats.nServices));
711  ui->peerLastSend->setText(stats->nodeStats.nLastSend ? GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nLastSend) : tr("never"));
712  ui->peerLastRecv->setText(stats->nodeStats.nLastRecv ? GUIUtil::formatDurationStr(GetSystemTimeInSeconds() - stats->nodeStats.nLastRecv) : tr("never"));
713  ui->peerBytesSent->setText(FormatBytes(stats->nodeStats.nSendBytes));
714  ui->peerBytesRecv->setText(FormatBytes(stats->nodeStats.nRecvBytes));
716  ui->peerPingTime->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingTime));
717  ui->peerPingWait->setText(GUIUtil::formatPingTime(stats->nodeStats.dPingWait));
718  ui->timeoffset->setText(GUIUtil::formatTimeOffset(stats->nodeStats.nTimeOffset));
719  ui->peerVersion->setText(QString("%1").arg(QString::number(stats->nodeStats.nVersion)));
720  ui->peerSubversion->setText(QString::fromStdString(stats->nodeStats.cleanSubVer));
721  ui->peerDirection->setText(stats->nodeStats.fInbound ? tr("Inbound") : tr("Outbound"));
722  ui->peerHeight->setText(QString("%1").arg(QString::number(stats->nodeStats.nStartingHeight)));
723  ui->peerWhitelisted->setText(stats->nodeStats.fWhitelisted ? tr("Yes") : tr("No"));
724 
725  // This check fails for example if the lock was busy and
726  // nodeStateStats couldn't be fetched.
727  if (stats->fNodeStateStatsAvailable) {
728  // Ban score is init to 0
729  ui->peerBanScore->setText(QString("%1").arg(stats->nodeStateStats.nMisbehavior));
730 
731  // Sync height is init to -1
732  if (stats->nodeStateStats.nSyncHeight > -1)
733  ui->peerSyncHeight->setText(QString("%1").arg(stats->nodeStateStats.nSyncHeight));
734  else
735  ui->peerSyncHeight->setText(tr("Unknown"));
736 
737  // Common height is init to -1
738  if (stats->nodeStateStats.nCommonHeight > -1)
739  ui->peerCommonHeight->setText(QString("%1").arg(stats->nodeStateStats.nCommonHeight));
740  else
741  ui->peerCommonHeight->setText(tr("Unknown"));
742  }
743 
744  ui->detailWidget->show();
745 }
746 
747 void RPCConsole::resizeEvent(QResizeEvent* event)
748 {
749  QWidget::resizeEvent(event);
750 }
751 
752 void RPCConsole::showEvent(QShowEvent* event)
753 {
754  QWidget::showEvent(event);
755 
757  return;
758 
759  // start PeerTableModel auto refresh
762 }
763 
764 void RPCConsole::hideEvent(QHideEvent* event)
765 {
766  QWidget::hideEvent(event);
767 
769  return;
770 
771  // stop PeerTableModel auto refresh
774 }
775 
777 {
779 }
780 
781 void RPCConsole::showPeersTableContextMenu(const QPoint& point)
782 {
783  QModelIndex index = ui->peerWidget->indexAt(point);
784  if (index.isValid())
785  peersTableContextMenu->exec(QCursor::pos());
786 }
787 
788 void RPCConsole::showBanTableContextMenu(const QPoint& point)
789 {
790  QModelIndex index = ui->banlistWidget->indexAt(point);
791  if (index.isValid())
792  banTableContextMenu->exec(QCursor::pos());
793 }
794 
796 {
797  if(!g_connman)
798  return;
799  // Get currently selected peer address
800  NodeId id = GUIUtil::getEntryData(ui->peerWidget, 0, PeerTableModel::NetNodeId).toInt();
801  // Find the node, disconnect it and clear the selected node
802  if(g_connman->DisconnectNode(id))
804 }
805 
807 {
808  if (!clientModel || !g_connman)
809  return;
810 
811  // No node selected exit out
812  if (cachedNodeid == -1)
813  return;
814 
815  // Get currently selected peer address
816  int selectedNodeRow = clientModel->getPeerTableModel()->getRowByNodeId(cachedNodeid);
817  if (selectedNodeRow < 0)
818  return;
819 
820  // Get nodeStats and we will use the addrName string(ip address)
821  const CNodeCombinedStats* stats = clientModel->getPeerTableModel()->getNodeStats(selectedNodeRow);
822 
823  std::string nStr = stats->nodeStats.addrName;
824  std::string addr;
825  int port = 0;
826  SplitHostPort(nStr, port, addr);
827  CNetAddr resolved;
828 
829  if (!LookupHost(addr.c_str(), resolved, false))
830  return;
831  g_connman->Ban(resolved, BanReasonManuallyAdded, bantime);
834 }
835 
837 {
838  if (!clientModel)
839  return;
840 
841  // Get currently selected ban address
842  QString strNode = GUIUtil::getEntryData(ui->banlistWidget, 0, BanTableModel::Address).toString();
843  CSubNet possibleSubnet;
844 
845  LookupSubNet(strNode.toStdString().c_str(), possibleSubnet);
846  if (possibleSubnet.IsValid() && g_connman)
847  {
848  g_connman->Unban(possibleSubnet);
850  }
851 }
852 
854 {
855  ui->peerWidget->selectionModel()->clearSelection();
856  cachedNodeid = -1;
857  ui->detailWidget->hide();
858  ui->peerHeading->setText(tr("Select a peer to view detailed information."));
859 }
860 
862 {
863  if (!clientModel)
864  return;
865 
866  bool visible = clientModel->getBanTableModel()->shouldShow();
867  ui->banlistWidget->setVisible(visible);
868  ui->banHeading->setVisible(visible);
869 }
@ BanReasonManuallyAdded
Definition: addrdb.h:25
const CChainParams & Params()
Return the currently selected parameters.
Network address.
Definition: netaddress.h:120
std::string addrLocal
Definition: net.h:607
double dPingWait
Definition: net.h:606
uint64_t nRecvBytes
Definition: net.h:602
std::string addrName
Definition: net.h:594
bool fInbound
Definition: net.h:597
bool fWhitelisted
Definition: net.h:604
uint64_t nSendBytes
Definition: net.h:600
int64_t nTimeConnected
Definition: net.h:592
double dPingTime
Definition: net.h:605
int64_t nLastRecv
Definition: net.h:591
ServiceFlags nServices
Definition: net.h:589
int nStartingHeight
Definition: net.h:599
int64_t nTimeOffset
Definition: net.h:593
int nVersion
Definition: net.h:595
NodeId nodeid
Definition: net.h:588
std::string cleanSubVer
Definition: net.h:596
int64_t nLastSend
Definition: net.h:590
std::vector< std::string > listCommands() const
Returns a list of registered commands.
Definition: server.cpp:520
bool IsValid() const
Model for PIVX network client.
Definition: clientmodel.h:50
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut)
QString getLastBlockHash() const
QString clientName() const
quint64 getTotalBytesRecv() const
quint64 getTotalBytesSent() const
void startMasternodesTimer()
PeerTableModel * getPeerTableModel()
void numBlocksChanged(int count)
void stopMasternodesTimer()
QDateTime getLastBlockDate() const
void strMasternodesChanged(const QString &strMasternodes)
void numConnectionsChanged(int count)
int getNumBlocks()
bool getNetworkActive() const
Return true if network activity in core is enabled.
QString formatClientStartupTime() const
int getNumConnections(unsigned int flags=CONNECTIONS_ALL) const
Return number of connections, default is in- and outbound (total)
Definition: clientmodel.cpp:63
BanTableModel * getBanTableModel()
QString dataDir() const
QString formatFullVersion() const
void networkActiveChanged(bool networkActive)
const CNodeCombinedStats * getNodeStats(int idx)
int getRowByNodeId(NodeId nodeid)
Local Bitcoin RPC console.
Definition: rpcconsole.h:33
void showBackups()
Show folder with wallet backups in default browser.
Definition: rpcconsole.cpp:776
QMenu * peersTableContextMenu
Definition: rpcconsole.h:152
void updateNodeDetail(const CNodeCombinedStats *stats)
show detailed information on ui about selected node
Definition: rpcconsole.cpp:699
void resizeEvent(QResizeEvent *event)
Definition: rpcconsole.cpp:747
WalletModel * walletModel
Definition: rpcconsole.h:147
void handleRestart(QStringList args)
Get restart command-line parameters and handle restart.
void browseHistory(int offset)
Go forward or back in history.
Definition: rpcconsole.cpp:510
void setWalletModel(WalletModel *model)
Definition: rpcconsole.cpp:290
void setMasternodeCount(const QString &strMasternodes)
Set number of masternodes shown in the UI.
Definition: rpcconsole.cpp:483
void peerSelected(const QItemSelection &selected, const QItemSelection &deselected)
Handle selection of peer in peers list.
Definition: rpcconsole.cpp:638
RPCTimerInterface * rpcTimerInterface
Definition: rpcconsole.h:154
NodeId cachedNodeid
Definition: rpcconsole.h:150
void on_lineEdit_returnPressed()
Definition: rpcconsole.cpp:488
QStringList history
Definition: rpcconsole.h:148
void buildParameterlist(QString arg)
Build parameter list for restart.
Definition: rpcconsole.cpp:356
void walletResync()
Restart wallet with "-resync".
Definition: rpcconsole.cpp:335
void setClientModel(ClientModel *model)
Definition: rpcconsole.cpp:173
void message(int category, const QString &msg)
Definition: rpcconsole.h:80
Ui::RPCConsole * ui
Definition: rpcconsole.h:145
void updateTrafficStats(quint64 totalBytesIn, quint64 totalBytesOut)
update traffic statistics
Definition: rpcconsole.cpp:592
void setTrafficGraphRange(int mins)
Definition: rpcconsole.cpp:586
void updateNetworkState(int num_connections)
Update UI with latest network info from model.
Definition: rpcconsole.cpp:443
void cmdRequest(const QString &command)
void walletUpgrade()
Restart wallet with "-upgradewallet".
Definition: rpcconsole.cpp:323
void disconnectSelectedNode()
Disconnect a selected node on the Peers tab.
Definition: rpcconsole.cpp:795
@ BANTIME_COLUMN_WIDTH
Definition: rpcconsole.h:142
@ ADDRESS_COLUMN_WIDTH
Definition: rpcconsole.h:138
@ SUBVERSION_COLUMN_WIDTH
Definition: rpcconsole.h:139
@ PING_COLUMN_WIDTH
Definition: rpcconsole.h:140
@ BANSUBNET_COLUMN_WIDTH
Definition: rpcconsole.h:141
QCompleter * autoCompleter
Definition: rpcconsole.h:151
void showRepair()
Switch to wallet-repair tab and show.
Definition: rpcconsole.cpp:622
virtual bool eventFilter(QObject *obj, QEvent *event)
Definition: rpcconsole.cpp:123
void walletRescan()
Restart wallet with "-rescan".
Definition: rpcconsole.cpp:305
void showMNConfEditor()
Open external (default) editor with masternode.conf.
Definition: rpcconsole.cpp:633
void showPeersTableContextMenu(const QPoint &point)
Show custom context menu on Peers tab.
Definition: rpcconsole.cpp:781
void showPeers()
Switch to peers tab and show.
Definition: rpcconsole.cpp:616
void setNumBlocks(int count)
Set number of blocks shown in the UI.
Definition: rpcconsole.cpp:474
void unbanSelectedNode()
Unban a selected node on the Bans tab.
Definition: rpcconsole.cpp:836
void clearSelectedNode()
clear the selected node
Definition: rpcconsole.cpp:853
void on_sldGraphRange_valueChanged(int value)
change the time range of the network traffic graph
Definition: rpcconsole.cpp:567
void reject()
Definition: rpcconsole.cpp:420
void stopExecutor()
void setNumConnections(int count)
Set number of connections shown in the UI.
Definition: rpcconsole.cpp:460
ClientModel * clientModel
Definition: rpcconsole.h:146
void banSelectedNode(int bantime)
Ban a selected node on the Peers tab.
Definition: rpcconsole.cpp:806
void clear()
Definition: rpcconsole.cpp:377
int historyPtr
Definition: rpcconsole.h:149
void scrollToEnd()
Scroll console view to end.
Definition: rpcconsole.cpp:561
void hideEvent(QHideEvent *event)
Definition: rpcconsole.cpp:764
void showConfEditor()
Open external (default) editor with pivx.conf.
Definition: rpcconsole.cpp:628
void walletZaptxes2()
Restart wallet with "-zapwallettxes=2".
Definition: rpcconsole.cpp:317
void walletZaptxes1()
Restart wallet with "-zapwallettxes=1".
Definition: rpcconsole.cpp:311
void on_tabWidget_currentChanged(int index)
Definition: rpcconsole.cpp:547
void walletReindex()
Restart wallet with "-reindex".
Definition: rpcconsole.cpp:329
void startExecutor()
Definition: rpcconsole.cpp:523
void setNetworkActive(bool networkActive)
Set network state shown in the UI.
Definition: rpcconsole.cpp:468
void walletSalvage()
Wallet repair options.
Definition: rpcconsole.cpp:299
void on_openDebugLogfileButton_clicked()
open the debug.log from the current datadir
Definition: rpcconsole.cpp:556
void showBanTableContextMenu(const QPoint &point)
Show custom context menu on Bans tab.
Definition: rpcconsole.cpp:788
void showInfo()
Switch to info tab and show.
Definition: rpcconsole.cpp:598
void showConsole()
Switch to console tab and show.
Definition: rpcconsole.cpp:604
RPCConsole(QWidget *parent)
Definition: rpcconsole.cpp:60
void showEvent(QShowEvent *event)
Definition: rpcconsole.cpp:752
void showOrHideBanTableIfRequired()
Hides ban table if no bans are present.
Definition: rpcconsole.cpp:861
QMenu * banTableContextMenu
Definition: rpcconsole.h:153
void peerLayoutChanged()
Handle updated peer information.
Definition: rpcconsole.cpp:650
static QString FormatBytes(quint64 bytes)
Definition: rpcconsole.cpp:574
void showNetwork()
Switch to network tab and show.
Definition: rpcconsole.cpp:610
void reply(int category, const QString &command)
void request(const QString &command)
Definition: rpcexecutor.cpp:35
static QString categoryClass(int category)
Definition: rpcexecutor.cpp:18
Interface to PIVX wallet from Qt view code.
Definition: walletmodel.h:109
QString getWalletPath()
@ CONNECTIONS_IN
Definition: clientmodel.h:43
@ CONNECTIONS_OUT
Definition: clientmodel.h:44
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:90
bool openDebugLogfile()
Definition: guiutil.cpp:413
QString HtmlEscape(const QString &str, bool fMultiLine)
Definition: guiutil.cpp:251
bool showBackups()
Definition: guiutil.cpp:428
QString formatPingTime(double dPingTime)
Definition: guiutil.cpp:734
bool openConfigfile()
Definition: guiutil.cpp:418
void saveWindowGeometry(const QString &strSetting, QWidget *parent)
Save window size and position.
Definition: guiutil.cpp:606
bool openMNConfigfile()
Definition: guiutil.cpp:423
void restoreWindowGeometry(const QString &strSetting, const QSize &defaultSize, QWidget *parent)
Restore window size and position.
Definition: guiutil.cpp:613
QString formatDurationStr(int secs)
Definition: guiutil.cpp:686
QVariant getEntryData(QAbstractItemView *view, int column, int role)
Return a field of the currently selected entry as a QString.
Definition: guiutil.cpp:278
QString formatTimeOffset(int64_t nTimeOffset)
Definition: guiutil.cpp:739
QString formatServicesStr(quint64 mask)
Definition: guiutil.cpp:706
int NodeId
Definition: net.h:109
void SplitHostPort(std::string in, int &portOut, std::string &hostOut)
Definition: netbase.cpp:71
bool LookupHost(const std::string &name, std::vector< CNetAddr > &vIP, unsigned int nMaxSolutions, bool fAllowLookup)
Definition: netbase.cpp:149
bool LookupSubNet(const std::string &strSubnet, CSubNet &ret)
Definition: netbase.cpp:673
const struct @24 ICON_MAPPING[]
const QString ZAPTXES1("-zapwallettxes=1")
const QString ZAPTXES2("-zapwallettxes=2")
const QSize ICON_SIZE(24, 24)
const QString UPGRADEWALLET("-upgradewallet")
const int INITIAL_TRAFFIC_GRAPH_MINS
Definition: rpcconsole.cpp:39
const int CONSOLE_HISTORY
Definition: rpcconsole.cpp:36
const QString SALVAGEWALLET("-salvagewallet")
const QString REINDEX("-reindex")
const QString RESYNC("-resync")
const char * url
Definition: rpcconsole.cpp:51
const QString RESCAN("-rescan")
const char * source
Definition: rpcconsole.cpp:52
void RPCSetTimerInterfaceIfUnset(RPCTimerInterface *iface)
Set factory function for timers, but only if unset.
Definition: server.cpp:539
void RPCUnsetTimerInterface(RPCTimerInterface *iface)
Unset factory function for timers.
Definition: server.cpp:550
CRPCTable tableRPC
Definition: server.cpp:565
CNodeStateStats nodeStateStats
CNodeStats nodeStats
int64_t GetSystemTimeInSeconds()
Returns the system time (not mockable)
Definition: utiltime.cpp:69