Skip to content

Commit

Permalink
TransactionHistory: guard tx info list against concurrent access
Browse files Browse the repository at this point in the history
  • Loading branch information
xiphon committed Dec 4, 2019
1 parent d5f4d5d commit 9d5eb00
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 31 deletions.
74 changes: 43 additions & 31 deletions src/libwalletqt/TransactionHistory.cpp
Expand Up @@ -32,10 +32,13 @@

#include <QFile>
#include <QDebug>
#include <QReadLocker>
#include <QWriteLocker>


TransactionInfo *TransactionHistory::transaction(int index)
{
QReadLocker locker(&m_tinfoLock);

if (index < 0 || index >= m_tinfo.size()) {
qCritical("%s: no transaction info for index %d", __FUNCTION__, index);
Expand All @@ -53,41 +56,48 @@ TransactionInfo *TransactionHistory::transaction(int index)

QList<TransactionInfo *> TransactionHistory::getAll(quint32 accountIndex) const
{
// XXX this invalidates previously saved history that might be used by model
emit refreshStarted();
qDeleteAll(m_tinfo);
m_tinfo.clear();

QDateTime firstDateTime = QDateTime(QDate(2014, 4, 18)); // the genesis block
QDateTime lastDateTime = QDateTime::currentDateTime().addDays(1); // tomorrow (guard against jitter and timezones)
quint64 lastTxHeight = 0;
m_locked = false;
m_minutesToUnlock = 0;
TransactionHistory * parent = const_cast<TransactionHistory*>(this);
for (const auto i : m_pimpl->getAll()) {
TransactionInfo * ti = new TransactionInfo(i, parent);
if (ti->subaddrAccount() != accountIndex) {
delete ti;
continue;
}
m_tinfo.append(ti);
// looking for transactions timestamp scope
if (ti->timestamp() >= lastDateTime) {
lastDateTime = ti->timestamp();
}
if (ti->timestamp() <= firstDateTime) {
firstDateTime = ti->timestamp();
}
quint64 requiredConfirmations = (ti->blockHeight() < ti->unlockTime()) ? ti->unlockTime() - ti->blockHeight() : 10;
// store last tx height
if (ti->confirmations() < requiredConfirmations && ti->blockHeight() >= lastTxHeight) {
lastTxHeight = ti->blockHeight();
// TODO: Fetch block time and confirmations needed from wallet2?
m_minutesToUnlock = (requiredConfirmations - ti->confirmations()) * 2;
m_locked = true;
}

emit refreshStarted();

{
QWriteLocker locker(&m_tinfoLock);

// XXX this invalidates previously saved history that might be used by model
qDeleteAll(m_tinfo);
m_tinfo.clear();

quint64 lastTxHeight = 0;
m_locked = false;
m_minutesToUnlock = 0;
TransactionHistory * parent = const_cast<TransactionHistory*>(this);
for (const auto i : m_pimpl->getAll()) {
TransactionInfo * ti = new TransactionInfo(i, parent);
if (ti->subaddrAccount() != accountIndex) {
delete ti;
continue;
}
m_tinfo.append(ti);
// looking for transactions timestamp scope
if (ti->timestamp() >= lastDateTime) {
lastDateTime = ti->timestamp();
}
if (ti->timestamp() <= firstDateTime) {
firstDateTime = ti->timestamp();
}
quint64 requiredConfirmations = (ti->blockHeight() < ti->unlockTime()) ? ti->unlockTime() - ti->blockHeight() : 10;
// store last tx height
if (ti->confirmations() < requiredConfirmations && ti->blockHeight() >= lastTxHeight) {
lastTxHeight = ti->blockHeight();
// TODO: Fetch block time and confirmations needed from wallet2?
m_minutesToUnlock = (requiredConfirmations - ti->confirmations()) * 2;
m_locked = true;
}

}
}

emit refreshFinished();

if (m_firstDateTime != firstDateTime) {
Expand All @@ -112,6 +122,8 @@ void TransactionHistory::refresh(quint32 accountIndex)

quint64 TransactionHistory::count() const
{
QReadLocker locker(&m_tinfoLock);

return m_tinfo.count();
}

Expand Down
2 changes: 2 additions & 0 deletions src/libwalletqt/TransactionHistory.h
Expand Up @@ -31,6 +31,7 @@

#include <QObject>
#include <QList>
#include <QReadWriteLock>
#include <QDateTime>

namespace Monero {
Expand Down Expand Up @@ -76,6 +77,7 @@ public slots:
friend class Wallet;
Monero::TransactionHistory * m_pimpl;
mutable QList<TransactionInfo*> m_tinfo;
mutable QReadWriteLock m_tinfoLock;
mutable QDateTime m_firstDateTime;
mutable QDateTime m_lastDateTime;
mutable int m_minutesToUnlock;
Expand Down

0 comments on commit 9d5eb00

Please sign in to comment.