aboutsummaryrefslogtreecommitdiff
path: root/src/wallet/api
diff options
context:
space:
mode:
Diffstat (limited to 'src/wallet/api')
-rw-r--r--src/wallet/api/transaction_history.cpp34
-rw-r--r--src/wallet/api/transaction_history.h2
-rw-r--r--src/wallet/api/wallet.cpp52
-rw-r--r--src/wallet/api/wallet.h4
4 files changed, 71 insertions, 21 deletions
diff --git a/src/wallet/api/transaction_history.cpp b/src/wallet/api/transaction_history.cpp
index 86dff85a4..fa939c08c 100644
--- a/src/wallet/api/transaction_history.cpp
+++ b/src/wallet/api/transaction_history.cpp
@@ -60,11 +60,24 @@ TransactionHistoryImpl::~TransactionHistoryImpl()
int TransactionHistoryImpl::count() const
{
- return m_history.size();
+ boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
+ int result = m_history.size();
+ return result;
+}
+
+TransactionInfo *TransactionHistoryImpl::transaction(int index) const
+{
+ boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
+ // sanity check
+ if (index < 0)
+ return nullptr;
+ unsigned index_ = static_cast<unsigned>(index);
+ return index_ < m_history.size() ? m_history[index_] : nullptr;
}
TransactionInfo *TransactionHistoryImpl::transaction(const std::string &id) const
{
+ boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
auto itr = std::find_if(m_history.begin(), m_history.end(),
[&](const TransactionInfo * ti) {
return ti->hash() == id;
@@ -74,11 +87,17 @@ TransactionInfo *TransactionHistoryImpl::transaction(const std::string &id) cons
std::vector<TransactionInfo *> TransactionHistoryImpl::getAll() const
{
+ boost::shared_lock<boost::shared_mutex> lock(m_historyMutex);
return m_history;
}
void TransactionHistoryImpl::refresh()
{
+ // multithreaded access:
+ // boost::lock_guard<boost::mutex> guarg(m_historyMutex);
+ // for "write" access, locking exclusively
+ boost::unique_lock<boost::shared_mutex> lock(m_historyMutex);
+
// TODO: configurable values;
uint64_t min_height = 0;
uint64_t max_height = (uint64_t)-1;
@@ -88,8 +107,6 @@ void TransactionHistoryImpl::refresh()
delete t;
m_history.clear();
-
-
// transactions are stored in wallet2:
// - confirmed_transfer_details - out transfers
// - unconfirmed_transfer_details - pending out transfers
@@ -188,16 +205,5 @@ void TransactionHistoryImpl::refresh()
ti->m_timestamp = pd.m_timestamp;
m_history.push_back(ti);
}
-
}
-TransactionInfo *TransactionHistoryImpl::transaction(int index) const
-{
- // sanity check
- if (index < 0)
- return nullptr;
- unsigned index_ = static_cast<unsigned>(index);
- return index_ < m_history.size() ? m_history[index_] : nullptr;
-}
-
-}
diff --git a/src/wallet/api/transaction_history.h b/src/wallet/api/transaction_history.h
index 171fd2210..1b6617ead 100644
--- a/src/wallet/api/transaction_history.h
+++ b/src/wallet/api/transaction_history.h
@@ -29,6 +29,7 @@
// Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
#include "wallet/wallet2_api.h"
+#include <boost/thread/shared_mutex.hpp>
namespace Bitmonero {
@@ -51,6 +52,7 @@ private:
// TransactionHistory is responsible of memory management
std::vector<TransactionInfo*> m_history;
WalletImpl *m_wallet;
+ mutable boost::shared_mutex m_historyMutex;
};
}
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
index 16321a5a2..a93e194b9 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -54,8 +54,9 @@ namespace {
struct Wallet2CallbackImpl : public tools::i_wallet2_callback
{
- Wallet2CallbackImpl()
+ Wallet2CallbackImpl(WalletImpl * wallet)
: m_listener(nullptr)
+ , m_wallet(wallet)
{
}
@@ -93,7 +94,8 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
LOG_PRINT_L3(__FUNCTION__ << ": money received. height: " << height
<< ", tx: " << tx_hash
<< ", amount: " << print_money(amount));
- if (m_listener) {
+ // do not signal on received tx if wallet is not syncronized completely
+ if (m_listener && m_wallet->synchronized()) {
m_listener->moneyReceived(tx_hash, amount);
m_listener->updated();
}
@@ -107,7 +109,8 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
LOG_PRINT_L3(__FUNCTION__ << ": money spent. height: " << height
<< ", tx: " << tx_hash
<< ", amount: " << print_money(amount));
- if (m_listener) {
+ // do not signal on sent tx if wallet is not syncronized completely
+ if (m_listener && m_wallet->synchronized()) {
m_listener->moneySpent(tx_hash, amount);
m_listener->updated();
}
@@ -119,6 +122,7 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
}
WalletListener * m_listener;
+ WalletImpl * m_wallet;
};
Wallet::~Wallet() {}
@@ -166,12 +170,16 @@ uint64_t Wallet::maximumAllowedAmount()
///////////////////////// WalletImpl implementation ////////////////////////
WalletImpl::WalletImpl(bool testnet)
- :m_wallet(nullptr), m_status(Wallet::Status_Ok), m_trustedDaemon(false),
- m_wallet2Callback(nullptr), m_recoveringFromSeed(false)
+ :m_wallet(nullptr)
+ , m_status(Wallet::Status_Ok)
+ , m_trustedDaemon(false)
+ , m_wallet2Callback(nullptr)
+ , m_recoveringFromSeed(false)
+ , m_synchronized(false)
{
m_wallet = new tools::wallet2(testnet);
m_history = new TransactionHistoryImpl(this);
- m_wallet2Callback = new Wallet2CallbackImpl;
+ m_wallet2Callback = new Wallet2CallbackImpl(this);
m_wallet->callback(m_wallet2Callback);
m_refreshThreadDone = false;
m_refreshEnabled = false;
@@ -201,7 +209,6 @@ bool WalletImpl::create(const std::string &path, const std::string &password, co
bool keys_file_exists;
bool wallet_file_exists;
tools::wallet2::wallet_exists(path, keys_file_exists, wallet_file_exists);
- // TODO: figure out how to setup logger;
LOG_PRINT_L3("wallet_path: " << path << "");
LOG_PRINT_L3("keys_file_exists: " << std::boolalpha << keys_file_exists << std::noboolalpha
<< " wallet_file_exists: " << std::boolalpha << wallet_file_exists << std::noboolalpha);
@@ -438,6 +445,28 @@ uint64_t WalletImpl::daemonBlockChainHeight() const
return result;
}
+uint64_t WalletImpl::daemonBlockChainTargetHeight() const
+{
+ std::string err;
+ uint64_t result = m_wallet->get_daemon_blockchain_target_height(err);
+ if (!err.empty()) {
+ LOG_ERROR(__FUNCTION__ << ": " << err);
+ result = 0;
+ m_errorString = err;
+ m_status = Status_Error;
+
+ } else {
+ m_status = Status_Ok;
+ m_errorString = "";
+ }
+ return result;
+}
+
+bool WalletImpl::synchronized() const
+{
+ return m_synchronized;
+}
+
bool WalletImpl::refresh()
{
clearStatus();
@@ -706,6 +735,15 @@ void WalletImpl::doRefresh()
boost::lock_guard<boost::mutex> guarg(m_refreshMutex2);
try {
m_wallet->refresh();
+ if (!m_synchronized) {
+ m_synchronized = true;
+ }
+ // assuming if we have empty history, it wasn't initialized yet
+ // for futher history changes client need to update history in
+ // "on_money_received" and "on_money_sent" callbacks
+ if (m_history->count() == 0) {
+ m_history->refresh();
+ }
} catch (const std::exception &e) {
m_status = Status_Error;
m_errorString = e.what();
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
index 5706b2bf5..98a5f2d09 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -77,6 +77,8 @@ public:
uint64_t unlockedBalance() const;
uint64_t blockChainHeight() const;
uint64_t daemonBlockChainHeight() const;
+ uint64_t daemonBlockChainTargetHeight() const;
+ bool synchronized() const;
bool refresh();
void refreshAsync();
void setAutoRefreshInterval(int millis);
@@ -107,6 +109,7 @@ private:
private:
friend class PendingTransactionImpl;
friend class TransactionHistoryImpl;
+ friend class Wallet2CallbackImpl;
tools::wallet2 * m_wallet;
mutable std::atomic<int> m_status;
@@ -132,6 +135,7 @@ private:
// so it shouldn't be considered as new and pull blocks (slow-refresh)
// instead of pulling hashes (fast-refresh)
bool m_recoveringFromSeed;
+ std::atomic<bool> m_synchronized;
};