Merge pull request 'Libwalletqt: update with upstream' (#140) from tobtoht/feather:libwalletqt_syncing into master

Reviewed-on: https://git.wownero.com/feather/feather/pulls/140
This commit is contained in:
tobtoht 2020-11-08 07:16:57 +00:00
commit d76b688ec4
2 changed files with 93 additions and 14 deletions

View file

@ -3,6 +3,10 @@
#include "Wallet.h" #include "Wallet.h"
#include <chrono>
#include <stdexcept>
#include <thread>
#include "PendingTransaction.h" #include "PendingTransaction.h"
#include "UnsignedTransaction.h" #include "UnsignedTransaction.h"
#include "TransactionHistory.h" #include "TransactionHistory.h"
@ -28,6 +32,8 @@
#include <QVector> #include <QVector>
#include <QMutexLocker> #include <QMutexLocker>
#include "utils/ScopeGuard.h"
namespace { namespace {
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5; static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30; static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30;
@ -101,6 +107,20 @@ bool Wallet::disconnected() const
return m_disconnected; return m_disconnected;
} }
bool Wallet::refreshing() const
{
return m_refreshing;
}
void Wallet::refreshingSet(bool value)
{
if (m_refreshing.exchange(value) != value)
{
emit refreshingChanged();
}
}
void Wallet::setConnectionStatus(ConnectionStatus value) void Wallet::setConnectionStatus(ConnectionStatus value)
{ {
if (m_connectionStatus == value) if (m_connectionStatus == value)
@ -245,7 +265,7 @@ void Wallet::initAsync(
emit walletCreationHeightChanged(); emit walletCreationHeightChanged();
qDebug() << "init async finished - starting refresh"; qDebug() << "init async finished - starting refresh";
connected(true); connected(true);
m_walletImpl->startRefresh(); startRefresh();
} }
}); });
if (future.first) if (future.first)
@ -456,20 +476,14 @@ bool Wallet::importOutputs(const QString& path) {
return m_walletImpl->importOutputs(path.toStdString()); return m_walletImpl->importOutputs(path.toStdString());
} }
bool Wallet::refresh() void Wallet::startRefresh()
{ {
qDebug() << "refresh async"; m_refreshEnabled = true;
m_walletImpl->refreshAsync();
} }
void Wallet::startRefresh() const void Wallet::pauseRefresh()
{ {
m_walletImpl->startRefresh(); m_refreshEnabled = false;
}
void Wallet::pauseRefresh() const
{
m_walletImpl->pauseRefresh();
} }
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id, PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
@ -580,6 +594,29 @@ bool Wallet::submitTxFile(const QString &fileName) const
return m_walletImpl->importKeyImages(fileName.toStdString() + "_keyImages"); return m_walletImpl->importKeyImages(fileName.toStdString() + "_keyImages");
} }
bool Wallet::refresh(bool historyAndSubaddresses /* = true */)
{
refreshingSet(true);
const auto cleanup = sg::make_scope_guard([this]() noexcept {
refreshingSet(false);
});
{
QMutexLocker locker(&m_asyncMutex);
bool result = m_walletImpl->refresh();
if (historyAndSubaddresses)
{
m_history->refresh(currentSubaddressAccount());
m_subaddress->refresh(currentSubaddressAccount());
m_subaddressAccount->getAll();
}
if (result)
emit updated();
return result;
}
}
void Wallet::commitTransactionAsync(PendingTransaction *t) void Wallet::commitTransactionAsync(PendingTransaction *t)
{ {
m_scheduler.run([this, t] { m_scheduler.run([this, t] {
@ -1063,6 +1100,8 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
, m_subaddressAccount(nullptr) , m_subaddressAccount(nullptr)
, m_subaddressAccountModel(nullptr) , m_subaddressAccountModel(nullptr)
, m_coinsModel(nullptr) , m_coinsModel(nullptr)
, m_refreshEnabled(false)
, m_refreshing(false)
, m_scheduler(this) , m_scheduler(this)
{ {
m_history = new TransactionHistory(m_walletImpl->history(), this); m_history = new TransactionHistory(m_walletImpl->history(), this);
@ -1081,12 +1120,17 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
m_connectionStatusRunning = false; m_connectionStatusRunning = false;
m_daemonUsername = ""; m_daemonUsername = "";
m_daemonPassword = ""; m_daemonPassword = "";
startRefreshThread();
} }
Wallet::~Wallet() Wallet::~Wallet()
{ {
qDebug("~Wallet: Closing wallet"); qDebug("~Wallet: Closing wallet");
pauseRefresh();
m_walletImpl->stop();
m_scheduler.shutdownWaitForFinished(); m_scheduler.shutdownWaitForFinished();
delete m_addressBook; delete m_addressBook;
@ -1116,3 +1160,32 @@ Wallet::~Wallet()
m_walletListener = NULL; m_walletListener = NULL;
qDebug("m_walletImpl deleted"); qDebug("m_walletImpl deleted");
} }
void Wallet::startRefreshThread()
{
const auto future = m_scheduler.run([this] {
constexpr const std::chrono::seconds refreshInterval{10};
constexpr const std::chrono::milliseconds intervalResolution{100};
auto last = std::chrono::steady_clock::now();
while (!m_scheduler.stopping())
{
if (m_refreshEnabled)
{
const auto now = std::chrono::steady_clock::now();
const auto elapsed = now - last;
if (elapsed >= refreshInterval)
{
refresh(false);
last = std::chrono::steady_clock::now();
}
}
std::this_thread::sleep_for(intervalResolution);
}
});
if (!future.first)
{
throw std::runtime_error("failed to start auto refresh thread");
}
}

View file

@ -50,6 +50,7 @@ class Wallet : public QObject, public PassprasePrompter
{ {
Q_OBJECT Q_OBJECT
Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged) Q_PROPERTY(bool disconnected READ disconnected NOTIFY disconnectedChanged)
Q_PROPERTY(bool refreshing READ refreshing NOTIFY refreshingChanged)
Q_PROPERTY(QString seed READ getSeed) Q_PROPERTY(QString seed READ getSeed)
Q_PROPERTY(QString seedLanguage READ getSeedLanguage) Q_PROPERTY(QString seedLanguage READ getSeedLanguage)
Q_PROPERTY(Status status READ status) Q_PROPERTY(Status status READ status)
@ -199,11 +200,11 @@ public:
Q_INVOKABLE bool importOutputs(const QString& path); Q_INVOKABLE bool importOutputs(const QString& path);
//! refreshes the wallet //! refreshes the wallet
Q_INVOKABLE bool refresh(); Q_INVOKABLE bool refresh(bool historyAndSubaddresses = false);
// pause/resume refresh // pause/resume refresh
Q_INVOKABLE void startRefresh() const; Q_INVOKABLE void startRefresh();
Q_INVOKABLE void pauseRefresh() const; Q_INVOKABLE void pauseRefresh();
//! returns current wallet's block height //! returns current wallet's block height
//! (can be less than daemon's blockchain height when wallet sync in progress) //! (can be less than daemon's blockchain height when wallet sync in progress)
@ -411,6 +412,7 @@ signals:
void currentSubaddressAccountChanged() const; void currentSubaddressAccountChanged() const;
void disconnectedChanged() const; void disconnectedChanged() const;
void proxyAddressChanged() const; void proxyAddressChanged() const;
void refreshingChanged() const;
private: private:
Wallet(QObject * parent = nullptr); Wallet(QObject * parent = nullptr);
@ -428,9 +430,13 @@ private:
const QString& proxyAddress); const QString& proxyAddress);
bool disconnected() const; bool disconnected() const;
bool refreshing() const;
void refreshingSet(bool value);
void setConnectionStatus(ConnectionStatus value); void setConnectionStatus(ConnectionStatus value);
QString getProxyAddress() const; QString getProxyAddress() const;
void setProxyAddress(QString address); void setProxyAddress(QString address);
void startRefreshThread();
private: private:
friend class WalletManager; friend class WalletManager;