Dogecoin Core  1.14.2
P2P Digital Currency
clientmodel.cpp
Go to the documentation of this file.
1 // Copyright (c) 2011-2016 The Bitcoin Core developers
2 // Distributed under the MIT software license, see the accompanying
3 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
4 
5 #include "clientmodel.h"
6 
7 #include "bantablemodel.h"
8 #include "guiconstants.h"
9 #include "guiutil.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 <stdint.h>
23 
24 #include <QDebug>
25 #include <QTimer>
26 
27 #include <boost/bind/bind.hpp>
28 
29 class CBlockIndex;
30 
31 static const int64_t nClientStartupTime = GetTime();
32 static int64_t nLastHeaderTipUpdateNotification = 0;
33 static int64_t nLastBlockTipUpdateNotification = 0;
34 
35 ClientModel::ClientModel(OptionsModel *_optionsModel, QObject *parent) :
36  QObject(parent),
37  optionsModel(_optionsModel),
38  peerTableModel(0),
39  banTableModel(0),
40  pollTimer(0)
41 {
44  peerTableModel = new PeerTableModel(this);
45  banTableModel = new BanTableModel(this);
46  pollTimer = new QTimer(this);
47  connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
48  pollTimer->start(MODEL_UPDATE_DELAY);
49 
51 }
52 
54 {
56 }
57 
58 int ClientModel::getNumConnections(unsigned int flags) const
59 {
61 
62  if(flags == CONNECTIONS_IN)
63  connections = CConnman::CONNECTIONS_IN;
64  else if (flags == CONNECTIONS_OUT)
65  connections = CConnman::CONNECTIONS_OUT;
66  else if (flags == CONNECTIONS_ALL)
67  connections = CConnman::CONNECTIONS_ALL;
68 
69  if(g_connman)
70  return g_connman->GetNodeCount(connections);
71  return 0;
72 }
73 
75 {
76  LOCK(cs_main);
77  return chainActive.Height();
78 }
79 
81 {
82  if (cachedBestHeaderHeight == -1) {
83  // make sure we initially populate the cache via a cs_main lock
84  // otherwise we need to wait for a tip update
85  LOCK(cs_main);
86  if (pindexBestHeader) {
89  }
90  }
92 }
93 
95 {
96  if (cachedBestHeaderTime == -1) {
97  LOCK(cs_main);
98  if (pindexBestHeader) {
101  }
102  }
103  return cachedBestHeaderTime;
104 }
105 
107 {
108  if(!g_connman)
109  return 0;
110  return g_connman->GetTotalBytesRecv();
111 }
112 
114 {
115  if(!g_connman)
116  return 0;
117  return g_connman->GetTotalBytesSent();
118 }
119 
121 {
122  LOCK(cs_main);
123 
124  if (chainActive.Tip())
125  return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime());
126 
127  return QDateTime::fromTime_t(Params().GenesisBlock().GetBlockTime()); // Genesis block's time of current network
128 }
129 
131 {
132  return mempool.size();
133 }
134 
136 {
137  return mempool.DynamicMemoryUsage();
138 }
139 
141 {
142  CBlockIndex *tip = const_cast<CBlockIndex *>(tipIn);
143  if (!tip)
144  {
145  LOCK(cs_main);
146  tip = chainActive.Tip();
147  }
148  return GuessVerificationProgress(Params().TxData(), tip);
149 }
150 
152 {
153  // no locking required at this point
154  // the following calls will acquire the required lock
157 }
158 
159 void ClientModel::updateNumConnections(int numConnections)
160 {
161  Q_EMIT numConnectionsChanged(numConnections);
162 }
163 
164 void ClientModel::updateNetworkActive(bool networkActive)
165 {
166  Q_EMIT networkActiveChanged(networkActive);
167 }
168 
169 void ClientModel::updateAlert(const QString &hash, int status)
170 {
171  // Show error message notification for new alert
172  if(status == CT_NEW)
173  {
174  uint256 hash_256;
175  hash_256.SetHex(hash.toStdString());
176  CAlert alert = CAlert::getAlertByHash(hash_256);
177  if(!alert.IsNull())
178  {
179  Q_EMIT message(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), CClientUIInterface::ICON_ERROR);
180  }
181  }
182 
184 }
185 
187 {
188  return IsInitialBlockDownload();
189 }
190 
192 {
193  if (fReindex)
194  return BLOCK_SOURCE_REINDEX;
195  else if (fImporting)
196  return BLOCK_SOURCE_DISK;
197  else if (getNumConnections() > 0)
198  return BLOCK_SOURCE_NETWORK;
199 
200  return BLOCK_SOURCE_NONE;
201 }
202 
204 {
205  if (g_connman) {
206  g_connman->SetNetworkActive(active);
207  }
208 }
209 
211 {
212  if (g_connman) {
213  return g_connman->GetNetworkActive();
214  }
215  return false;
216 }
217 
219 {
220  return QString::fromStdString(GetWarnings("gui"));
221 }
222 
224 {
225  return optionsModel;
226 }
227 
229 {
230  return peerTableModel;
231 }
232 
234 {
235  return banTableModel;
236 }
237 
239 {
240  return QString::fromStdString(FormatFullVersion());
241 }
242 
244 {
245  return QString::fromStdString(strSubVersion);
246 }
247 
249 {
251 }
252 
254 {
255  return QDateTime::fromTime_t(nClientStartupTime).toString();
256 }
257 
258 QString ClientModel::dataDir() const
259 {
261 }
262 
264 {
266 }
267 
268 // Handlers for core signals
269 static void ShowProgress(ClientModel *clientmodel, const std::string &title, int nProgress)
270 {
271  // emits signal "showProgress"
272  QMetaObject::invokeMethod(clientmodel, "showProgress", Qt::QueuedConnection,
273  Q_ARG(QString, QString::fromStdString(title)),
274  Q_ARG(int, nProgress));
275 }
276 
277 static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections)
278 {
279  // Too noisy: qDebug() << "NotifyNumConnectionsChanged: " + QString::number(newNumConnections);
280  QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection,
281  Q_ARG(int, newNumConnections));
282 }
283 
284 static void NotifyNetworkActiveChanged(ClientModel *clientmodel, bool networkActive)
285 {
286  QMetaObject::invokeMethod(clientmodel, "updateNetworkActive", Qt::QueuedConnection,
287  Q_ARG(bool, networkActive));
288 }
289 
290 static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
291 {
292  qDebug() << "NotifyAlertChanged: " + QString::fromStdString(hash.GetHex()) + " status=" + QString::number(status);
293  QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection,
294  Q_ARG(QString, QString::fromStdString(hash.GetHex())),
295  Q_ARG(int, status));
296 }
297 
298 static void BannedListChanged(ClientModel *clientmodel)
299 {
300  qDebug() << QString("%1: Requesting update for peer banlist").arg(__func__);
301  QMetaObject::invokeMethod(clientmodel, "updateBanlist", Qt::QueuedConnection);
302 }
303 
304 static void BlockTipChanged(ClientModel *clientmodel, bool initialSync, const CBlockIndex *pIndex, bool fHeader)
305 {
306  // lock free async UI updates in case we have a new block tip
307  // during initial sync, only update the UI if the last update
308  // was > 250ms (MODEL_UPDATE_DELAY) ago
309  int64_t now = 0;
310  if (initialSync)
311  now = GetTimeMillis();
312 
313  int64_t& nLastUpdateNotification = fHeader ? nLastHeaderTipUpdateNotification : nLastBlockTipUpdateNotification;
314 
315  if (fHeader) {
316  // cache best headers time and height to reduce future cs_main locks
317  clientmodel->cachedBestHeaderHeight = pIndex->nHeight;
318  clientmodel->cachedBestHeaderTime = pIndex->GetBlockTime();
319  }
320  // if we are in-sync, update the UI regardless of last update time
321  if (!initialSync || now - nLastUpdateNotification > MODEL_UPDATE_DELAY) {
322  //pass a async signal to the UI thread
323  QMetaObject::invokeMethod(clientmodel, "numBlocksChanged", Qt::QueuedConnection,
324  Q_ARG(int, pIndex->nHeight),
325  Q_ARG(QDateTime, QDateTime::fromTime_t(pIndex->GetBlockTime())),
326  Q_ARG(double, clientmodel->getVerificationProgress(pIndex)),
327  Q_ARG(bool, fHeader));
328  nLastUpdateNotification = now;
329  }
330 }
331 
333 {
334  // Connect signals to client
335  uiInterface.ShowProgress.connect(boost::bind(ShowProgress, this,
336  boost::placeholders::_1,
337  boost::placeholders::_2));
338  uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this,
339  boost::placeholders::_1));
340  uiInterface.NotifyNetworkActiveChanged.connect(boost::bind(NotifyNetworkActiveChanged, this,
341  boost::placeholders::_1));
342  uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this,
343  boost::placeholders::_1,
344  boost::placeholders::_2));
345  uiInterface.BannedListChanged.connect(boost::bind(BannedListChanged, this));
346  uiInterface.NotifyBlockTip.connect(boost::bind(BlockTipChanged, this,
347  boost::placeholders::_1,
348  boost::placeholders::_2, false));
349  uiInterface.NotifyHeaderTip.connect(boost::bind(BlockTipChanged, this,
350  boost::placeholders::_1,
351  boost::placeholders::_2, true));
352 }
353 
355 {
356  // Disconnect signals from client
357  uiInterface.ShowProgress.disconnect(boost::bind(ShowProgress, this,
358  boost::placeholders::_1,
359  boost::placeholders::_2));
360  uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this,
361  boost::placeholders::_1));
362  uiInterface.NotifyNetworkActiveChanged.disconnect(boost::bind(NotifyNetworkActiveChanged, this,
363  boost::placeholders::_1));
364  uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this,
365  boost::placeholders::_1,
366  boost::placeholders::_2));
367  uiInterface.BannedListChanged.disconnect(boost::bind(BannedListChanged, this));
368  uiInterface.NotifyBlockTip.disconnect(boost::bind(BlockTipChanged, this,
369  boost::placeholders::_1,
370  boost::placeholders::_2, false));
371  uiInterface.NotifyHeaderTip.disconnect(boost::bind(BlockTipChanged, this,
372  boost::placeholders::_1,
373  boost::placeholders::_2, true));
374 }
int flags
Definition: bitcoin-tx.cpp:468
const CChainParams & Params()
Return the currently selected parameters.
Qt model providing information about connected peers, similar to the "getpeerinfo" RPC call.
Definition: bantablemodel.h:38
An alert is a combination of a serialized CUnsignedAlert and a signature.
Definition: alert.h:77
bool IsNull() const
Definition: alert.cpp:93
static CAlert getAlertByHash(const uint256 &hash)
Definition: alert.cpp:140
The block chain is a tree shaped structure starting with the genesis block at the root,...
Definition: chain.h:158
int64_t GetBlockTime() const
Definition: chain.h:273
int nHeight
height of the entry in the chain. The genesis block has height 0
Definition: chain.h:170
CBlockIndex * Tip() const
Returns the index entry for the tip of this chain, or NULL if none.
Definition: chain.h:443
int Height() const
Return the maximal height in the chain.
Definition: chain.h:474
boost::signals2::signal< void(const uint256 &hash, ChangeType status)> NotifyAlertChanged
New, updated or cancelled alert.
Definition: ui_interface.h:95
boost::signals2::signal< void(bool, const CBlockIndex *)> NotifyBlockTip
New block has been accepted.
Definition: ui_interface.h:104
boost::signals2::signal< void(int newNumConnections)> NotifyNumConnectionsChanged
Number of network connections changed.
Definition: ui_interface.h:86
boost::signals2::signal< void(const std::string &title, int nProgress)> ShowProgress
Show progress e.g.
Definition: ui_interface.h:101
boost::signals2::signal< void(bool, const CBlockIndex *)> NotifyHeaderTip
Best header has changed.
Definition: ui_interface.h:107
boost::signals2::signal< void(void)> BannedListChanged
Banlist did change.
Definition: ui_interface.h:110
boost::signals2::signal< void(bool networkActive)> NotifyNetworkActiveChanged
Network activity state changed.
Definition: ui_interface.h:89
NumConnections
Definition: net.h:128
@ CONNECTIONS_IN
Definition: net.h:130
@ CONNECTIONS_NONE
Definition: net.h:129
@ CONNECTIONS_ALL
Definition: net.h:132
@ CONNECTIONS_OUT
Definition: net.h:131
size_t DynamicMemoryUsage() const
Definition: txmempool.cpp:1000
unsigned long size()
Definition: txmempool.h:620
std::string strStatusBar
Definition: alert.h:46
Model for Bitcoin network client.
Definition: clientmodel.h:42
void bytesChanged(quint64 totalBytesIn, quint64 totalBytesOut)
void updateBanlist()
void setNetworkActive(bool active)
Toggle network activity state in core.
QString getStatusBarWarnings() const
Return warnings to be displayed in status bar.
void updateAlert(const QString &hash, int status)
int getHeaderTipHeight() const
Definition: clientmodel.cpp:80
std::atomic< int64_t > cachedBestHeaderTime
Definition: clientmodel.h:88
quint64 getTotalBytesRecv() const
quint64 getTotalBytesSent() const
PeerTableModel * getPeerTableModel()
void updateNetworkActive(bool networkActive)
std::atomic< int > cachedBestHeaderHeight
Definition: clientmodel.h:87
void updateNumConnections(int numConnections)
size_t getMempoolDynamicUsage() const
Return the dynamic memory usage of the mempool.
void updateTimer()
void message(const QString &title, const QString &message, unsigned int style)
Fired when a message should be reported to the user.
QDateTime getLastBlockDate() const
void numConnectionsChanged(int count)
int getNumBlocks() const
Definition: clientmodel.cpp:74
int64_t getHeaderTipTime() const
Definition: clientmodel.cpp:94
double getVerificationProgress(const CBlockIndex *tip) const
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:58
enum BlockSource getBlockSource() const
Returns enum BlockSource of the current importing/syncing state.
OptionsModel * optionsModel
Definition: clientmodel.h:91
BanTableModel * banTableModel
Definition: clientmodel.h:93
BanTableModel * getBanTableModel()
void unsubscribeFromCoreSignals()
long getMempoolSize() const
Return number of transactions in the mempool.
QTimer * pollTimer
Definition: clientmodel.h:95
void alertsChanged(const QString &warnings)
QString dataDir() const
OptionsModel * getOptionsModel()
QString formatFullVersion() const
PeerTableModel * peerTableModel
Definition: clientmodel.h:92
ClientModel(OptionsModel *optionsModel, QObject *parent=0)
Definition: clientmodel.cpp:35
QString formatSubVersion() const
void mempoolSizeChanged(long count, size_t mempoolSizeInBytes)
bool isReleaseVersion() const
bool inInitialBlockDownload() const
Return true if core is doing initial block download.
void subscribeToCoreSignals()
void networkActiveChanged(bool networkActive)
Interface from Qt to configuration data structure for Bitcoin client.
Definition: optionsmodel.h:23
Qt model providing information about connected peers, similar to the "getpeerinfo" RPC call.
void SetHex(const char *psz)
Definition: uint256.cpp:30
std::string GetHex() const
Definition: uint256.cpp:21
256-bit opaque blob.
Definition: uint256.h:123
@ CONNECTIONS_IN
Definition: clientmodel.h:35
@ CONNECTIONS_OUT
Definition: clientmodel.h:36
@ CONNECTIONS_ALL
Definition: clientmodel.h:37
BlockSource
Definition: clientmodel.h:26
@ BLOCK_SOURCE_NETWORK
Definition: clientmodel.h:30
@ BLOCK_SOURCE_DISK
Definition: clientmodel.h:29
@ BLOCK_SOURCE_NONE
Definition: clientmodel.h:27
@ BLOCK_SOURCE_REINDEX
Definition: clientmodel.h:28
std::string FormatFullVersion()
#define CLIENT_VERSION_IS_RELEASE
Set to true for release, false for prerelease or test build.
Definition: clientversion.h:23
std::unique_ptr< CConnman > g_connman
Definition: init.cpp:75
QString boostPathToQString(const boost::filesystem::path &path)
Definition: guiutil.cpp:875
std::string strSubVersion
Subversion as sent to the P2P network in version messages.
Definition: net.cpp:75
#define LOCK(cs)
Definition: sync.h:177
CClientUIInterface uiInterface
Definition: ui_interface.cpp:8
ChangeType
General change type (added, updated, removed).
Definition: ui_interface.h:22
@ CT_NEW
Definition: ui_interface.h:23
const boost::filesystem::path & GetDataDir(bool fNetSpecific)
Definition: util.cpp:513
int64_t GetTimeMillis()
Definition: utiltime.cpp:33
int64_t GetTime()
GetTimeMicros() and GetTimeMillis() both return the system time, but in different units.
Definition: utiltime.cpp:19
CCriticalSection cs_main
Global state.
Definition: validation.cpp:61
CTxMemPool mempool(::minRelayTxFee)
bool IsInitialBlockDownload()
Check whether we are doing an initial block download (synchronizing from disk or network)
bool fReindex
Definition: validation.cpp:70
CBlockIndex * pindexBestHeader
Best header we've seen so far (used for getheaders queries' starting points).
Definition: validation.cpp:65
CChain chainActive
The currently-connected chain of blocks (protected by cs_main).
Definition: validation.cpp:64
double GuessVerificationProgress(const ChainTxData &data, CBlockIndex *pindex)
Guess how far we are in the verification process at the given block index.
std::atomic_bool fImporting
std::string GetWarnings(const std::string &strFor)
Format a string that describes several potential problems detected by the core.
Definition: warnings.cpp:51