aboutsummaryrefslogtreecommitdiff
path: root/src/libwalletqt
diff options
context:
space:
mode:
authorxiphon <xiphon@protonmail.com>2020-10-09 12:04:53 +0000
committerxiphon <xiphon@protonmail.com>2020-10-09 14:11:05 +0000
commit39d9d7d071dd9ed7a942578a7db520ac0ec08f5e (patch)
treece1d65d44cddca4e5860fcb08a0f1a7ff0ff56fd /src/libwalletqt
parentd3943ca2a9e1fa27ec9141ed94e1d4fb530aca31 (diff)
downloadmonzero-gui-39d9d7d071dd9ed7a942578a7db520ac0ec08f5e.tar.gz
monzero-gui-39d9d7d071dd9ed7a942578a7db520ac0ec08f5e.tar.xz
monzero-gui-39d9d7d071dd9ed7a942578a7db520ac0ec08f5e.zip
Wallet: rework wallet refreshing
Diffstat (limited to 'src/libwalletqt')
-rw-r--r--src/libwalletqt/Wallet.cpp107
-rw-r--r--src/libwalletqt/Wallet.h24
2 files changed, 90 insertions, 41 deletions
diff --git a/src/libwalletqt/Wallet.cpp b/src/libwalletqt/Wallet.cpp
index 508f105e..454dca29 100644
--- a/src/libwalletqt/Wallet.cpp
+++ b/src/libwalletqt/Wallet.cpp
@@ -27,6 +27,11 @@
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Wallet.h"
+
+#include <chrono>
+#include <stdexcept>
+#include <thread>
+
#include "PendingTransaction.h"
#include "UnsignedTransaction.h"
#include "TransactionHistory.h"
@@ -50,6 +55,8 @@
#include <QVector>
#include <QMutexLocker>
+#include "qt/ScopeGuard.h"
+
namespace {
static const int DAEMON_BLOCKCHAIN_HEIGHT_CACHE_TTL_SECONDS = 5;
static const int DAEMON_BLOCKCHAIN_TARGET_HEIGHT_CACHE_TTL_SECONDS = 30;
@@ -124,6 +131,19 @@ bool Wallet::disconnected() const
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)
{
if (m_connectionStatus == value)
@@ -196,7 +216,7 @@ void Wallet::storeAsync(const QJSValue &callback, const QString &path /* = "" */
{
const auto future = m_scheduler.run(
[this, path] {
- QMutexLocker locker(&m_storeMutex);
+ QMutexLocker locker(&m_asyncMutex);
return QJSValueList({m_walletImpl->store(path.toStdString())});
},
@@ -263,7 +283,7 @@ void Wallet::initAsync(
emit walletCreationHeightChanged();
qDebug() << "init async finished - starting refresh";
connected(true);
- m_walletImpl->startRefresh();
+ startRefresh();
}
});
if (future.first)
@@ -466,41 +486,37 @@ bool Wallet::importKeyImages(const QString& path)
return m_walletImpl->importKeyImages(path.toStdString());
}
-bool Wallet::refresh()
-{
- bool result = m_walletImpl->refresh();
- m_history->refresh(currentSubaddressAccount());
- m_subaddress->refresh(currentSubaddressAccount());
- m_subaddressAccount->getAll();
- if (result)
- emit updated();
- return result;
-}
-
-void Wallet::refreshAsync()
+bool Wallet::refresh(bool historyAndSubaddresses /* = true */)
{
- qDebug() << "refresh async";
- m_walletImpl->refreshAsync();
-}
+ refreshingSet(true);
+ const auto cleanup = sg::make_scope_guard([this]() noexcept {
+ refreshingSet(false);
+ });
-void Wallet::setAutoRefreshInterval(int seconds)
-{
- m_walletImpl->setAutoRefreshInterval(seconds);
-}
+ {
+ QMutexLocker locker(&m_asyncMutex);
-int Wallet::autoRefreshInterval() const
-{
- return m_walletImpl->autoRefreshInterval();
+ 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::startRefresh() const
+void Wallet::startRefresh()
{
- m_walletImpl->startRefresh();
+ m_refreshEnabled = true;
}
-void Wallet::pauseRefresh() const
+void Wallet::pauseRefresh()
{
- m_walletImpl->pauseRefresh();
+ m_refreshEnabled = false;
}
PendingTransaction *Wallet::createTransaction(const QString &dst_addr, const QString &payment_id,
@@ -874,6 +890,8 @@ bool Wallet::parse_uri(const QString &uri, QString &address, QString &payment_id
bool Wallet::rescanSpent()
{
+ QMutexLocker locker(&m_asyncMutex);
+
return m_walletImpl->rescanSpent();
}
@@ -1041,6 +1059,8 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
, m_subaddressModel(nullptr)
, m_subaddressAccount(nullptr)
, m_subaddressAccountModel(nullptr)
+ , m_refreshEnabled(false)
+ , m_refreshing(false)
, m_scheduler(this)
{
m_history = new TransactionHistory(m_walletImpl->history(), this);
@@ -1058,6 +1078,8 @@ Wallet::Wallet(Monero::Wallet *w, QObject *parent)
m_connectionStatusRunning = false;
m_daemonUsername = "";
m_daemonPassword = "";
+
+ startRefreshThread();
}
Wallet::~Wallet()
@@ -1090,3 +1112,32 @@ Wallet::~Wallet()
m_walletListener = NULL;
qDebug("m_walletImpl deleted");
}
+
+void Wallet::startRefreshThread()
+{
+ const auto future = m_scheduler.run([this] {
+ static constexpr const size_t refreshIntervalSec = 10;
+ static constexpr const size_t intervalResolutionMs = 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 = std::chrono::duration_cast<std::chrono::seconds>(now - last).count();
+ if (elapsed >= refreshIntervalSec)
+ {
+ refresh(false);
+ last = std::chrono::steady_clock::now();
+ }
+ }
+
+ std::this_thread::sleep_for(std::chrono::milliseconds(intervalResolutionMs));
+ }
+ });
+ if (!future.first)
+ {
+ throw std::runtime_error("failed to start auto refresh thread");
+ }
+}
diff --git a/src/libwalletqt/Wallet.h b/src/libwalletqt/Wallet.h
index b099a011..42e30336 100644
--- a/src/libwalletqt/Wallet.h
+++ b/src/libwalletqt/Wallet.h
@@ -63,6 +63,7 @@ class Wallet : public QObject, public PassprasePrompter
{
Q_OBJECT
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 seedLanguage READ getSeedLanguage)
Q_PROPERTY(Status status READ status)
@@ -207,20 +208,11 @@ public:
Q_INVOKABLE bool importKeyImages(const QString& path);
//! refreshes the wallet
- Q_INVOKABLE bool refresh();
-
- //! refreshes the wallet asynchronously
- Q_INVOKABLE void refreshAsync();
-
- //! setup auto-refresh interval in seconds
- Q_INVOKABLE void setAutoRefreshInterval(int seconds);
-
- //! return auto-refresh interval in seconds
- Q_INVOKABLE int autoRefreshInterval() const;
+ Q_INVOKABLE bool refresh(bool historyAndSubaddresses = true);
// pause/resume refresh
- Q_INVOKABLE void startRefresh() const;
- Q_INVOKABLE void pauseRefresh() const;
+ Q_INVOKABLE void startRefresh();
+ Q_INVOKABLE void pauseRefresh();
//! creates transaction
Q_INVOKABLE PendingTransaction * createTransaction(const QString &dst_addr, const QString &payment_id,
@@ -394,6 +386,7 @@ signals:
void currentSubaddressAccountChanged() const;
void disconnectedChanged() const;
void proxyAddressChanged() const;
+ void refreshingChanged() const;
private:
Wallet(QObject * parent = nullptr);
@@ -421,9 +414,12 @@ private:
const QString& proxyAddress);
bool disconnected() const;
+ bool refreshing() const;
+ void refreshingSet(bool value);
void setConnectionStatus(ConnectionStatus value);
QString getProxyAddress() const;
void setProxyAddress(QString address);
+ void startRefreshThread();
private:
friend class WalletManager;
@@ -454,15 +450,17 @@ private:
mutable SubaddressModel * m_subaddressModel;
SubaddressAccount * m_subaddressAccount;
mutable SubaddressAccountModel * m_subaddressAccountModel;
+ QMutex m_asyncMutex;
QMutex m_connectionStatusMutex;
bool m_connectionStatusRunning;
QString m_daemonUsername;
QString m_daemonPassword;
QString m_proxyAddress;
mutable QMutex m_proxyMutex;
+ std::atomic<bool> m_refreshEnabled;
+ std::atomic<bool> m_refreshing;
WalletListenerImpl *m_walletListener;
FutureScheduler m_scheduler;
- QMutex m_storeMutex;
};