Dash Core  0.12.2.1
P2P Digital Currency
clientmodel.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2015 The Bitcoin Core developers
2 // Copyright (c) 2014-2017 The Dash 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 #include "clientmodel.h"
7 
8 #include "bantablemodel.h"
9 #include "guiconstants.h"
10 #include "peertablemodel.h"
11 
12 #include "alert.h"
13 #include "chainparams.h"
14 #include "checkpoints.h"
15 #include "clientversion.h"
16 #include "validation.h"
17 #include "net.h"
18 #include "txmempool.h"
19 #include "ui_interface.h"
20 #include "util.h"
21 
22 #include "masternodeman.h"
23 #include "masternode-sync.h"
24 #include "privatesend.h"
25 
26 #include <stdint.h>
27 
28 #include <QDebug>
29 #include <QTimer>
30 
31 class CBlockIndex;
32 
33 static const int64_t nClientStartupTime = GetTime();
36 
37 ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
38  QObject(parent),
39  optionsModel(optionsModel),
40  peerTableModel(0),
41  cachedMasternodeCountString(""),
42  banTableModel(0),
43  pollTimer(0)
44 {
47  peerTableModel = new PeerTableModel(this);
48  banTableModel = new BanTableModel(this);
49  pollTimer = new QTimer(this);
50  connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
52 
53  pollMnTimer = new QTimer(this);
54  connect(pollMnTimer, SIGNAL(timeout()), this, SLOT(updateMnTimer()));
55  // no need to update as frequent as data for balances/txes/blocks
56  pollMnTimer->start(MODEL_UPDATE_DELAY * 4);
57 
59 }
60 
62 {
64 }
65 
66 int ClientModel::getNumConnections(unsigned int flags) const
67 {
69 
70  if(flags == CONNECTIONS_IN)
71  connections = CConnman::CONNECTIONS_IN;
72  else if (flags == CONNECTIONS_OUT)
73  connections = CConnman::CONNECTIONS_OUT;
74  else if (flags == CONNECTIONS_ALL)
75  connections = CConnman::CONNECTIONS_ALL;
76 
77  if(g_connman)
78  return g_connman->GetNodeCount(connections);
79  return 0;
80 }
81 
83 {
84  // return tr("Total: %1 (PS compatible: %2 / Enabled: %3) (IPv4: %4, IPv6: %5, TOR: %6)").arg(QString::number((int)mnodeman.size()))
85  return tr("Total: %1 (PS compatible: %2 / Enabled: %3)")
86  .arg(QString::number((int)mnodeman.size()))
87  .arg(QString::number((int)mnodeman.CountEnabled(MIN_PRIVATESEND_PEER_PROTO_VERSION)))
88  .arg(QString::number((int)mnodeman.CountEnabled()));
89  // .arg(QString::number((int)mnodeman.CountByIP(NET_IPV4)))
90  // .arg(QString::number((int)mnodeman.CountByIP(NET_IPV6)))
91  // .arg(QString::number((int)mnodeman.CountByIP(NET_TOR)));
92 }
93 
95 {
96  LOCK(cs_main);
97  return chainActive.Height();
98 }
99 
101 {
102  if (cachedBestHeaderHeight == -1) {
103  // make sure we initially populate the cache via a cs_main lock
104  // otherwise we need to wait for a tip update
105  LOCK(cs_main);
106  if (pindexBestHeader) {
109  }
110  }
111  return cachedBestHeaderHeight;
112 }
113 
115 {
116  if (cachedBestHeaderTime == -1) {
117  LOCK(cs_main);
118  if (pindexBestHeader) {
121  }
122  }
123  return cachedBestHeaderTime;
124 }
125 
127 {
128  if(!g_connman)
129  return 0;
130  return g_connman->GetTotalBytesRecv();
131 }
132 
134 {
135  if(!g_connman)
136  return 0;
137  return g_connman->GetTotalBytesSent();
138 }
139 
141 {
142  LOCK(cs_main);
143 
144  if (chainActive.Tip())
145  return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime());
146 
147  return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network
148 }
149 
151 {
152  return mempool.size();
153 }
154 
156 {
157  return mempool.DynamicMemoryUsage();
158 }
159 
161 {
162  CBlockIndex *tip = const_cast<CBlockIndex *>(tipIn);
163  if (!tip)
164  {
165  LOCK(cs_main);
166  tip = chainActive.Tip();
167  }
169 }
170 
172 {
173  // no locking required at this point
174  // the following calls will acquire the required lock
177 }
178 
180 {
181  QString newMasternodeCountString = getMasternodeCountString();
182 
183  if (cachedMasternodeCountString != newMasternodeCountString)
184  {
185  cachedMasternodeCountString = newMasternodeCountString;
186 
188  }
189 }
190 
191 void ClientModel::updateNumConnections(int numConnections)
192 {
193  Q_EMIT numConnectionsChanged(numConnections);
194 }
195 
196 void ClientModel::updateNetworkActive(bool networkActive)
197 {
198  Q_EMIT networkActiveChanged(networkActive);
199 }
200 
201 void ClientModel::updateAlert(const QString &hash, int status)
202 {
203  // Show error message notification for new alert
204  if(status == CT_NEW)
205  {
206  uint256 hash_256;
207  hash_256.SetHex(hash.toStdString());
208  CAlert alert = CAlert::getAlertByHash(hash_256);
209  if(!alert.IsNull())
210  {
211  Q_EMIT message(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), CClientUIInterface::ICON_ERROR);
212  }
213  }
214 
216 }
217 
219 {
220  return IsInitialBlockDownload();
221 }
222 
224 {
225  if (fReindex)
226  return BLOCK_SOURCE_REINDEX;
227  else if (fImporting)
228  return BLOCK_SOURCE_DISK;
229  else if (getNumConnections() > 0)
230  return BLOCK_SOURCE_NETWORK;
231 
232  return BLOCK_SOURCE_NONE;
233 }
234 
236 {
237  if (g_connman) {
238  g_connman->SetNetworkActive(active);
239  }
240 }
241 
243 {
244  if (g_connman) {
245  return g_connman->GetNetworkActive();
246  }
247  return false;
248 }
249 
251 {
252  return QString::fromStdString(GetWarnings("gui"));
253 }
254 
256 {
257  return optionsModel;
258 }
259 
261 {
262  return peerTableModel;
263 }
264 
266 {
267  return banTableModel;
268 }
269 
271 {
272  return QString::fromStdString(FormatFullVersion());
273 }
274 
276 {
277  return QString::fromStdString(strSubVersion);
278 }
279 
281 {
283 }
284 
285 QString ClientModel::clientName() const
286 {
287  return QString::fromStdString(CLIENT_NAME);
288 }
289 
291 {
292  return QDateTime::fromTime_t(nClientStartupTime).toString();
293 }
294 
295 QString ClientModel::dataDir() const
296 {
297  return QString::fromStdString(GetDataDir().string());
298 }
299 
301 {
303 }
304 
305 // Handlers for core signals
306 static void ShowProgress(ClientModel *clientmodel, const std::string &title, int nProgress)
307 {
308  // emits signal "showProgress"
309  QMetaObject::invokeMethod(clientmodel, "showProgress", Qt::QueuedConnection,
310  Q_ARG(QString, QString::fromStdString(title)),
311  Q_ARG(int, nProgress));
312 }
313 
314 static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections)
315 {
316  // Too noisy: qDebug() << "NotifyNumConnectionsChanged: " + QString::number(newNumConnections);
317  QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection,
318  Q_ARG(int, newNumConnections));
319 }
320 
321 static void NotifyNetworkActiveChanged(ClientModel *clientmodel, bool networkActive)
322 {
323  QMetaObject::invokeMethod(clientmodel, "updateNetworkActive", Qt::QueuedConnection,
324  Q_ARG(bool, networkActive));
325 }
326 
327 static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
328 {
329  qDebug() << "NotifyAlertChanged: " + QString::fromStdString(hash.GetHex()) + " status=" + QString::number(status);
330  QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection,
331  Q_ARG(QString, QString::fromStdString(hash.GetHex())),
332  Q_ARG(int, status));
333 }
334 
335 static void BannedListChanged(ClientModel *clientmodel)
336 {
337  qDebug() << QString("%1: Requesting update for peer banlist").arg(__func__);
338  QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection);
339 }
340 
341 static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CBlockIndex *pIndex, bool fHeader)
342 {
343  // lock free async UI updates in case we have a new block tip
344  // during initial sync, only update the UI if the last update
345  // was > 250ms (MODEL_UPDATE_DELAY) ago
346  int64_t now = 0;
347  if (initialSync)
348  now = GetTimeMillis();
349 
350  int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
351 
352  if (fHeader) {
353  // cache best headers time and height to reduce future cs_main locks
354  clientmodel->cachedBestHeaderHeight = pIndex->nHeight;
355  clientmodel->cachedBestHeaderTime = pIndex->GetBlockTime();
356  }
357  // if we are in-sync, update the UI regardless of last update time
358  if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) {
359  //pass a async signal to the UI thread
360  QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection,
361  Q_ARG(int, pIndex->nHeight),
362  Q_ARG(QDateTime, QDateTime::fromTime_t(pIndex->GetBlockTime())),
363  Q_ARG(double, clientmodel->getVerificationProgress(pIndex)),
364  Q_ARG(bool, fHeader));
365  nLastUpdateNotification = now;
366  }
367 }
368 
369 static void NotifyAdditionalDataSyncProgressChanged(ClientModel *clientmodel, double nSyncProgress)
370 {
371  QMetaObject::invokeMethod(clientmodel, "additionalDataSyncProgressChanged", Qt::QueuedConnection,
372  Q_ARG(double, nSyncProgress));
373 }
374 
376 {
377  // Connect signals to client
378  uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this, _1, _2));
380  uiInterface.NotifyNetworkActiveChanged.connect(boost::bind(NotifyNetworkActiveChanged, this, _1));
381  uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
382  uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this));
383  uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this, _1, _2, false));
384  uiInterface.NotifyHeaderTip.connect(boost::bind(BlockTipChanged, this, _1, _2, true));
386 }
387 
389 {
390  // Disconnect signals from client
391  uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this, _1, _2));
392  uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
393  uiInterface.NotifyNetworkActiveChanged.disconnect(boost::bind(NotifyNetworkActiveChanged, this, _1));
394  uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
395  uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this));
396  uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, false));
397  uiInterface.NotifyHeaderTip.disconnect(boost::bind(BlockTipChanged, this, _1, _2, true));
399 }
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:547
CMasternodeMan mnodeman
void subscribeToCoreSignals()
ClientModel(OptionsModel *optionsModel, QObject *parent=0)
Definition: clientmodel.cpp:37
unsigned long size()
Definition: txmempool.h:551
QString getStatusBarWarnings() const
Return warnings to be displayed in status bar.
static const int64_t nClientStartupTime
Definition: clientmodel.cpp:33
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes)
size_t getMempoolDynamicUsage() const
Return the dynamic memory usage of the mempool.
boost::signals2::signal< void(const uint256 &hash, ChangeType status)> NotifyAlertChanged
Definition: ui_interface.h:98
bool inInitialBlockDownload() const
Return true if core is doing initial block download.
enum BlockSource getBlockSource() const
Returns enum BlockSource of the current importing/syncing state.
boost::signals2::signal< void(void)> BannedListChanged
Definition: ui_interface.h:116
static void ShowProgress(ClientModel *clientmodel, const std::string &title, int nProgress)
CCriticalSection cs_main
Definition: validation.cpp:62
bool fReindex
Definition: validation.cpp:71
void message(const QString &title, const QString &message, unsigned int style)
Fired when a message should be reported to the user.
int64_t getHeaderTipTime() const
void updateAlert(const QString &hash, int status)
int flags
Definition: dash-tx.cpp:326
QTimer * pollMnTimer
Definition: clientmodel.h:100
boost::signals2::signal< void(bool, const CBlockIndex *)> NotifyBlockTip
Definition: ui_interface.h:107
int getNumBlocks() const
Definition: clientmodel.cpp:94
QString cachedMasternodeCountString
Definition: clientmodel.h:96
void updateNumConnections(int numConnections)
boost::signals2::signal< void(bool, const CBlockIndex *)> NotifyHeaderTip
Definition: ui_interface.h:110
void setNetworkActive(bool active)
Toggle network activity state in core.
Definition: alert.h:77
static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CBlockIndex *pIndex, bool fHeader)
static void NotifyAdditionalDataSyncProgressChanged(ClientModel *clientmodel, double nSyncProgress)
std::atomic< int64_t > cachedBestHeaderTime
Definition: clientmodel.h:91
bool isReleaseVersion() const
#define CLIENT_VERSION_IS_RELEASE
Set to true for release, false for prerelease or test build.
Definition: clientversion.h:23
static int64_t nLastHeaderTipUpdateNotification
Definition: clientmodel.cpp:34
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Definition: ui_interface.h:104
void strMasternodesChanged(const QString &strMasternodes)
BanTableModel * banTableModel
Definition: clientmodel.h:97
ChangeType
Definition: ui_interface.h:21
CBlockIndex * pindexBestHeader
Definition: validation.cpp:66
#define LOCK(cs)
Definition: sync.h:168
NumConnections
Definition: net.h:112
QString getMasternodeCountString() const
Definition: clientmodel.cpp:82
void updateNetworkActive(bool networkActive)
BlockSource
Definition: clientmodel.h:27
size_t DynamicMemoryUsage() const
Definition: txmempool.cpp:1000
CClientUIInterface uiInterface
Definition: init.cpp:130
void updateMnTimer()
PeerTableModel * peerTableModel
Definition: clientmodel.h:95
int Height() const
Definition: chain.h:397
bool IsInitialBlockDownload()
QString formatSubVersion() const
boost::signals2::signal< void(int newNumConnections)> NotifyNumConnectionsChanged
Definition: ui_interface.h:86
QString dataDir() const
CChain chainActive
Definition: validation.cpp:65
static CAlert getAlertByHash(const uint256 &hash)
Definition: alert.cpp:182
OptionsModel * optionsModel
Definition: clientmodel.h:94
static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
const std::string CLIENT_NAME
std::string strSubVersion
Definition: net.cpp:83
int size()
Return the number of (unique) Masternodes.
int getHeaderTipHeight() const
double GuessVerificationProgress(const CCheckpointData &data, CBlockIndex *pindex, bool fSigchecks)
Guess how far we are in the verification process at the given block index.
Definition: checkpoints.cpp:30
std::string FormatFullVersion()
static const int MODEL_UPDATE_DELAY
Definition: guiconstants.h:10
long getMempoolSize() const
Return number of transactions in the mempool.
QString formatFullVersion() const
static void BannedListChanged(ClientModel *clientmodel)
QString formatClientStartupTime() const
bool getNetworkActive() const
Return true if network activity in core is enabled.
CTxMemPool mempool
quint64 getTotalBytesRecv() const
int CountEnabled(int nProtocolVersion=-1)
std::string GetWarnings(const std::string &strFor)
const CChainParams & Params()
int64_t GetTimeMillis()
Definition: utiltime.cpp:34
static int64_t nLastBlockTipUpdateNotification
Definition: clientmodel.cpp:35
void updateBanlist()
bool fImporting
Definition: validation.cpp:70
static const int MIN_PRIVATESEND_PEER_PROTO_VERSION
minimum peer version accepted by mixing pool
Definition: privatesend.h:25
static void NotifyNetworkActiveChanged(ClientModel *clientmodel, bool networkActive)
std::string GetHex() const
Definition: uint256.cpp:21
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:103
CBlockIndex * Tip() const
Definition: chain.h:366
double getVerificationProgress(const CBlockIndex *tip) const
std::string strStatusBar
Definition: alert.h:47
void alertsChanged(const QString &warnings)
int64_t GetBlockTime() const
Definition: chain.h:223
int64_t GetTime()
For unit testing.
Definition: utiltime.cpp:20
std::atomic< int > cachedBestHeaderHeight
Definition: clientmodel.h:90
void unsubscribeFromCoreSignals()
boost::signals2::signal< void(double nSyncProgress)> NotifyAdditionalDataSyncProgressChanged
Definition: ui_interface.h:113
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut)
QTimer * pollTimer
Definition: clientmodel.h:99
bool IsNull() const
Definition: alert.cpp:93
void SetHex(const char *psz)
Definition: uint256.cpp:30
quint64 getTotalBytesSent() const
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:113
static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections)
boost::signals2::signal< void(bool networkActive)> NotifyNetworkActiveChanged
Definition: ui_interface.h:89
void numConnectionsChanged(int count)
QDateTime getLastBlockDate() const
QString clientName() const
OptionsModel * getOptionsModel()
void updateTimer()
BanTableModel * getBanTableModel()
int getNumConnections(unsigned int flags=CONNECTIONS_ALL) const
Return number of connections, default is in- and outbound (total)
Definition: clientmodel.cpp:66
void networkActiveChanged(bool networkActive)
PeerTableModel * getPeerTableModel()