0e4b317555
The new class is accessed via the Params() method and holds most things that vary between main, test and regtest networks. The regtest mode has two purposes, one is to run the bitcoind/bitcoinj comparison tool which compares two separate implementations of the Bitcoin protocol looking for divergence. The other is that when run, you get a local node which can mine a single block instantly, which is highly convenient for testing apps during development as there's no need to wait 10 minutes for a block on the testnet.
211 lines
6.0 KiB
C++
211 lines
6.0 KiB
C++
#include "clientmodel.h"
|
|
|
|
#include "guiconstants.h"
|
|
#include "optionsmodel.h"
|
|
#include "addresstablemodel.h"
|
|
#include "transactiontablemodel.h"
|
|
|
|
#include "chainparams.h"
|
|
#include "alert.h"
|
|
#include "main.h"
|
|
#include "checkpoints.h"
|
|
#include "ui_interface.h"
|
|
|
|
#include <QDateTime>
|
|
#include <QTimer>
|
|
|
|
static const int64 nClientStartupTime = GetTime();
|
|
|
|
ClientModel::ClientModel(OptionsModel *optionsModel, QObject *parent) :
|
|
QObject(parent), optionsModel(optionsModel),
|
|
cachedNumBlocks(0), cachedNumBlocksOfPeers(0),
|
|
cachedReindexing(0), cachedImporting(0),
|
|
numBlocksAtStartup(-1), pollTimer(0)
|
|
{
|
|
pollTimer = new QTimer(this);
|
|
pollTimer->setInterval(MODEL_UPDATE_DELAY);
|
|
pollTimer->start();
|
|
connect(pollTimer, SIGNAL(timeout()), this, SLOT(updateTimer()));
|
|
|
|
subscribeToCoreSignals();
|
|
}
|
|
|
|
ClientModel::~ClientModel()
|
|
{
|
|
unsubscribeFromCoreSignals();
|
|
}
|
|
|
|
int ClientModel::getNumConnections() const
|
|
{
|
|
return vNodes.size();
|
|
}
|
|
|
|
int ClientModel::getNumBlocks() const
|
|
{
|
|
return nBestHeight;
|
|
}
|
|
|
|
int ClientModel::getNumBlocksAtStartup()
|
|
{
|
|
if (numBlocksAtStartup == -1) numBlocksAtStartup = getNumBlocks();
|
|
return numBlocksAtStartup;
|
|
}
|
|
|
|
QDateTime ClientModel::getLastBlockDate() const
|
|
{
|
|
if (pindexBest)
|
|
return QDateTime::fromTime_t(pindexBest->GetBlockTime());
|
|
else if(!isTestNet())
|
|
return QDateTime::fromTime_t(1231006505); // Genesis block's time
|
|
else
|
|
return QDateTime::fromTime_t(1296688602); // Genesis block's time (testnet)
|
|
}
|
|
|
|
double ClientModel::getVerificationProgress() const
|
|
{
|
|
return Checkpoints::GuessVerificationProgress(pindexBest);
|
|
}
|
|
|
|
void ClientModel::updateTimer()
|
|
{
|
|
// 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();
|
|
int newNumBlocksOfPeers = getNumBlocksOfPeers();
|
|
|
|
// check for changed number of blocks we have, number of blocks peers claim to have, reindexing state and importing state
|
|
if (cachedNumBlocks != newNumBlocks || cachedNumBlocksOfPeers != newNumBlocksOfPeers ||
|
|
cachedReindexing != fReindex || cachedImporting != fImporting)
|
|
{
|
|
cachedNumBlocks = newNumBlocks;
|
|
cachedNumBlocksOfPeers = newNumBlocksOfPeers;
|
|
cachedReindexing = fReindex;
|
|
cachedImporting = fImporting;
|
|
|
|
// ensure we return the maximum of newNumBlocksOfPeers and newNumBlocks to not create weird displays in the GUI
|
|
emit numBlocksChanged(newNumBlocks, std::max(newNumBlocksOfPeers, newNumBlocks));
|
|
}
|
|
}
|
|
|
|
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());
|
|
}
|
|
|
|
bool ClientModel::isTestNet() const
|
|
{
|
|
return TestNet();
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
int ClientModel::getNumBlocksOfPeers() const
|
|
{
|
|
return GetNumBlocksOfPeers();
|
|
}
|
|
|
|
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: OutputDebugStringF("NotifyNumConnectionsChanged %i\n", newNumConnections);
|
|
QMetaObject::invokeMethod(clientmodel, "updateNumConnections", Qt::QueuedConnection,
|
|
Q_ARG(int, newNumConnections));
|
|
}
|
|
|
|
static void NotifyAlertChanged(ClientModel *clientmodel, const uint256 &hash, ChangeType status)
|
|
{
|
|
OutputDebugStringF("NotifyAlertChanged %s status=%i\n", hash.GetHex().c_str(), 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));
|
|
}
|