mirror of
https://github.com/dashpay/dash.git
synced 2024-12-28 13:32:47 +01:00
aa250f0453
Generally useless information. Only updates on connect time, not after that. Peers can easily lie and the median filter is not effective in preventing that. In the past it was used for progress display in the GUI but `CheckPoints::guessVerificationProgress` provides a better way that is now used. It was too easy to mislead it. Peers do lie about it in practice, see issue #4065. From the RPC, `getpeerinfo` gives the peer raw values, which are more useful.
238 lines
6.6 KiB
C++
238 lines
6.6 KiB
C++
// Copyright (c) 2011-2013 The Bitcoin developers
|
|
// Distributed under the MIT/X11 software license, see the accompanying
|
|
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
|
|
|
#include "clientmodel.h"
|
|
|
|
#include "guiconstants.h"
|
|
|
|
#include "alert.h"
|
|
#include "chainparams.h"
|
|
#include "checkpoints.h"
|
|
#include "main.h"
|
|
#include "net.h"
|
|
#include "ui_interface.h"
|
|
|
|
#include <stdint.h>
|
|
|
|
#include <QDateTime>
|
|
#include <QDebug>
|
|
#include <QTimer>
|
|
|
|
static const int64_t nClientStartupTime = GetTime();
|
|
|
|
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
|
|
QObject(parent), optionsModel(optionsModel),
|
|
cachedNumBlocks(0),
|
|
cachedReindexing(0), cachedImporting(0),
|
|
numBlocksAtStartup(-1), pollTimer(0)
|
|
{
|
|
pollTimer = new QTimer(this);
|
|
connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
|
|
pollTimer->start(MODEL_UPDATE_DELAY);
|
|
|
|
subscribeToCoreSignals();
|
|
}
|
|
|
|
ClientModel::~ClientModel()
|
|
{
|
|
unsubscribeFromCoreSignals();
|
|
}
|
|
|
|
int ClientModel::getNumConnections(unsigned int flags) const
|
|
{
|
|
LOCK(cs_vNodes);
|
|
if (flags == CONNECTIONS_ALL) // Shortcut if we want total
|
|
return vNodes.size();
|
|
|
|
int nNum = 0;
|
|
BOOST_FOREACH(CNode* pnode, vNodes)
|
|
if (flags & (pnode->fInbound ? CONNECTIONS_IN : CONNECTIONS_OUT))
|
|
nNum++;
|
|
|
|
return nNum;
|
|
}
|
|
|
|
int ClientModel::getNumBlocks() const
|
|
{
|
|
LOCK(cs_main);
|
|
return chainActive.Height();
|
|
}
|
|
|
|
int ClientModel::getNumBlocksAtStartup()
|
|
{
|
|
if (numBlocksAtStartup == -1) numBlocksAtStartup = getNumBlocks();
|
|
return numBlocksAtStartup;
|
|
}
|
|
|
|
quint64 ClientModel::getTotalBytesRecv() const
|
|
{
|
|
return CNode::GetTotalBytesRecv();
|
|
}
|
|
|
|
quint64 ClientModel::getTotalBytesSent() const
|
|
{
|
|
return CNode::GetTotalBytesSent();
|
|
}
|
|
|
|
QDateTime ClientModel::getLastBlockDate() const
|
|
{
|
|
LOCK(cs_main);
|
|
if (chainActive.Tip())
|
|
return QDateTime::fromTime_t(chainActive.Tip()->GetBlockTime());
|
|
else
|
|
return QDateTime::fromTime_t(Params().GenesisBlock().nTime); // Genesis block's time of current network
|
|
}
|
|
|
|
double ClientModel::getVerificationProgress() const
|
|
{
|
|
LOCK(cs_main);
|
|
return Checkpoints::GuessVerificationProgress(chainActive.Tip());
|
|
}
|
|
|
|
void ClientModel::updateTimer()
|
|
{
|
|
// Get required lock upfront. This avoids the GUI from getting stuck on
|
|
// periodical polls if the core is holding the locks for a longer time -
|
|
// for example, during a wallet rescan.
|
|
TRY_LOCK(cs_main, lockMain);
|
|
if(!lockMain)
|
|
return;
|
|
// Some quantities (such as number of blocks) change so fast that we don't want to be notified for each change.
|
|
// Periodically check and update with a timer.
|
|
int newNumBlocks = getNumBlocks();
|
|
|
|
// check for changed number of blocks we have, number of blocks peers claim to have, reindexing state and importing state
|
|
if (cachedNumBlocks != newNumBlocks ||
|
|
cachedReindexing != fReindex || cachedImporting != fImporting)
|
|
{
|
|
cachedNumBlocks = newNumBlocks;
|
|
cachedReindexing = fReindex;
|
|
cachedImporting = fImporting;
|
|
|
|
emit numBlocksChanged(newNumBlocks);
|
|
}
|
|
|
|
emit bytesChanged(getTotalBytesRecv(), getTotalBytesSent());
|
|
}
|
|
|
|
void ClientModel::updateNumConnections(int numConnections)
|
|
{
|
|
emit numConnectionsChanged(numConnections);
|
|
}
|
|
|
|
void ClientModel::updateAlert(const QString &hash, int status)
|
|
{
|
|
// Show error message notification for new alert
|
|
if(status == CT_NEW)
|
|
{
|
|
uint256 hash_256;
|
|
hash_256.SetHex(hash.toStdString());
|
|
CAlert alert = CAlert::getAlertByHash(hash_256);
|
|
if(!alert.IsNull())
|
|
{
|
|
emit message(tr("Network Alert"), QString::fromStdString(alert.strStatusBar), CClientUIInterface::ICON_ERROR);
|
|
}
|
|
}
|
|
|
|
emit alertsChanged(getStatusBarWarnings());
|
|
}
|
|
|
|
QString ClientModel::getNetworkName() const
|
|
{
|
|
QString netname(QString::fromStdString(Params().DataDir()));
|
|
if(netname.isEmpty())
|
|
netname = "main";
|
|
return netname;
|
|
}
|
|
|
|
bool ClientModel::inInitialBlockDownload() const
|
|
{
|
|
return IsInitialBlockDownload();
|
|
}
|
|
|
|
enum BlockSource ClientModel::getBlockSource() const
|
|
{
|
|
if (fReindex)
|
|
return BLOCK_SOURCE_REINDEX;
|
|
else if (fImporting)
|
|
return BLOCK_SOURCE_DISK;
|
|
else if (getNumConnections() > 0)
|
|
return BLOCK_SOURCE_NETWORK;
|
|
|
|
return BLOCK_SOURCE_NONE;
|
|
}
|
|
|
|
QString ClientModel::getStatusBarWarnings() const
|
|
{
|
|
return QString::fromStdString(GetWarnings("statusbar"));
|
|
}
|
|
|
|
OptionsModel *ClientModel::getOptionsModel()
|
|
{
|
|
return optionsModel;
|
|
}
|
|
|
|
QString ClientModel::formatFullVersion() const
|
|
{
|
|
return QString::fromStdString(FormatFullVersion());
|
|
}
|
|
|
|
QString ClientModel::formatBuildDate() const
|
|
{
|
|
return QString::fromStdString(CLIENT_DATE);
|
|
}
|
|
|
|
bool ClientModel::isReleaseVersion() const
|
|
{
|
|
return CLIENT_VERSION_IS_RELEASE;
|
|
}
|
|
|
|
QString ClientModel::clientName() const
|
|
{
|
|
return QString::fromStdString(CLIENT_NAME);
|
|
}
|
|
|
|
QString ClientModel::formatClientStartupTime() const
|
|
{
|
|
return QDateTime::fromTime_t(nClientStartupTime).toString();
|
|
}
|
|
|
|
// Handlers for core signals
|
|
static void NotifyBlocksChanged(ClientModel *clientmodel)
|
|
{
|
|
// This notification is too frequent. Don't trigger a signal.
|
|
// Don't remove it, though, as it might be useful later.
|
|
}
|
|
|
|
static void NotifyNumConnectionsChanged(ClientModel *clientmodel, int newNumConnections)
|
|
{
|
|
// Too noisy: qDebug() << "NotifyNumConnectionsChanged : " + QString::number(newNumConnections);
|
|
QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection,
|
|
Q_ARG(int, newNumConnections));
|
|
}
|
|
|
|
static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
|
|
{
|
|
qDebug() << "NotifyAlertChanged : " + QString::fromStdString(hash.GetHex()) + " status=" + QString::number(status);
|
|
QMetaObject::invokeMethod(clientmodel, "updateAlert", Qt::QueuedConnection,
|
|
Q_ARG(QString, QString::fromStdString(hash.GetHex())),
|
|
Q_ARG(int, status));
|
|
}
|
|
|
|
void ClientModel::subscribeToCoreSignals()
|
|
{
|
|
// Connect signals to client
|
|
uiInterface.NotifyBlocksChanged.connect(boost::bind(NotifyBlocksChanged, this));
|
|
uiInterface.NotifyNumConnectionsChanged.connect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
|
uiInterface.NotifyAlertChanged.connect(boost::bind(NotifyAlertChanged, this, _1, _2));
|
|
}
|
|
|
|
void ClientModel::unsubscribeFromCoreSignals()
|
|
{
|
|
// Disconnect signals from client
|
|
uiInterface.NotifyBlocksChanged.disconnect(boost::bind(NotifyBlocksChanged, this));
|
|
uiInterface.NotifyNumConnectionsChanged.disconnect(boost::bind(NotifyNumConnectionsChanged, this, _1));
|
|
uiInterface.NotifyAlertChanged.disconnect(boost::bind(NotifyAlertChanged, this, _1, _2));
|
|
}
|