diff --git a/src/wallet/MoneroWallet.cpp b/src/wallet/MoneroWallet.cpp index dab7387..3ca96a2 100644 --- a/src/wallet/MoneroWallet.cpp +++ b/src/wallet/MoneroWallet.cpp @@ -60,6 +60,11 @@ #include "mnemonics/english.h" #include "wallet/wallet_rpc_server_commands_defs.h" +#ifdef WIN32 +#include +#include +#endif + using namespace std; using namespace cryptonote; using namespace epee; @@ -72,7 +77,8 @@ namespace monero { // ------------------------- INITIALIZE CONSTANTS --------------------------- - static const int DEFAULT_CONNECTION_TIMEOUT_MILLIS = 1000 * 30; + static const int DEFAULT_REFRESH_INTERVAL_MILLIS = 1000 * 10; // default refresh interval 10 sec + static const int DEFAULT_CONNECTION_TIMEOUT_MILLIS = 1000 * 30; // default connection timeout 30 sec // ----------------------- INTERNAL PRIVATE HELPERS ----------------------- @@ -864,7 +870,7 @@ namespace monero { } // TODO: could return Wallet::ConnectionStatus_Disconnected, Wallet::ConnectionStatus_WrongVersion, Wallet::ConnectionStatus_Connected like wallet.cpp::connected() - bool MoneroWallet::getIsConnected() { + bool MoneroWallet::getIsConnected() const { uint32_t version = 0; isConnected = wallet2->check_connection(&version, NULL, DEFAULT_CONNECTION_TIMEOUT_MILLIS); // TODO: should this be updated elsewhere? if (!isConnected) return false; @@ -872,18 +878,16 @@ namespace monero { return isConnected; } - uint64_t MoneroWallet::getDaemonHeight() { - if (!isConnected) throw runtime_error("Wallet is not connected to daemon"); + uint64_t MoneroWallet::getDaemonHeight() const { + if (!isConnected) throw runtime_error("wallet is not connected to daemon"); std::string err; uint64_t result = wallet2->get_daemon_blockchain_height(err); if (!err.empty()) throw runtime_error(err); return result; - - throw runtime_error("getDaemonHeight() not implemented"); } - uint64_t MoneroWallet::getDaemonTargetHeight() { - if (!isConnected) throw runtime_error("Wallet is not connected to daemon"); + uint64_t MoneroWallet::getDaemonTargetHeight() const { + if (!isConnected) throw runtime_error("wallet is not connected to daemon"); std::string err; uint64_t result = wallet2->get_daemon_blockchain_target_height(err); if (!err.empty()) throw runtime_error(err); @@ -891,13 +895,13 @@ namespace monero { return result; } - bool MoneroWallet::getIsDaemonSynced() { - if (!isConnected) return false; + bool MoneroWallet::getIsDaemonSynced() const { + if (!isConnected) throw runtime_error("wallet is not connected to daemon"); uint64_t daemonHeight = getDaemonHeight(); return daemonHeight >= getDaemonTargetHeight() && daemonHeight > 1; } - bool MoneroWallet::getIsSynced() { + bool MoneroWallet::getIsSynced() const { return isSynced; } @@ -2275,6 +2279,11 @@ namespace monero { void MoneroWallet::initCommon() { cout << "MoneroWallet.cpp initCommon()" << endl; wallet2Listener = unique_ptr(new Wallet2Listener(*this, *wallet2)); + isConnected = false; + isSynced = false; + rescanOnSync = false; + autoSyncEnabled = false; + autoSyncThreadDone = false; // start auto sync loop autoSyncThread = boost::thread([this]() { @@ -2284,31 +2293,32 @@ namespace monero { void MoneroWallet::autoSyncThreadFunc() { cout << "autoSyncThreadFunc()" << endl; -// while (true) { -// boost::mutex::scoped_lock lock(autoSyncMutex); -// if (autoSyncThreadDone) break; -// if (autoSyncEnabled) { -// boost::posix_time::milliseconds wait_for_ms(autoSyncIntervalMillis.load()); -// syncCV.timed_wait(lock, wait_for_ms); -// } else { -// syncCV.wait(lock); -// } -// if (autoSyncEnabled) { -// doRefresh(); -// } -// } + while (true) { + boost::mutex::scoped_lock lock(autoSyncMutex); + if (autoSyncThreadDone) break; + if (autoSyncEnabled) { + boost::posix_time::milliseconds wait_for_ms(DEFAULT_REFRESH_INTERVAL_MILLIS); + syncCV.timed_wait(lock, wait_for_ms); + } else { + syncCV.wait(lock); + } + if (autoSyncEnabled) { + doSync(); + } + } } void MoneroWallet::doSync() { -// bool rescan = rescanOnSync.exchange(false); -// boost::lock_guard guarg(syncMutex); -// do { -// if (daemonSynced()) { -// if (rescan) wallet2->rescan_blockchain(false); -// wallet2->refresh(wallet2->is_trusted_daemon()); -// wallet2->find_and_save_rings(false); -// } -// } while (!rescan && (rescan = rescanOnSync.exchange(false))); // repeat if not rescanned and rescan was requested + bool rescan = rescanOnSync.exchange(false); + boost::lock_guard guarg(syncMutex); + do { + if (getIsDaemonSynced()) { + if (rescan) wallet2->rescan_blockchain(false); + wallet2->refresh(wallet2->is_trusted_daemon()); + if (!isSynced) isSynced = true; + wallet2->find_and_save_rings(false); + } + } while (!rescan && (rescan = rescanOnSync.exchange(false))); // repeat if not rescanned and rescan was requested } MoneroSyncResult MoneroWallet::syncAux(boost::optional startHeight, boost::optional endHeight, boost::optional listener) { diff --git a/src/wallet/MoneroWallet.h b/src/wallet/MoneroWallet.h index 1aa4091..5214101 100644 --- a/src/wallet/MoneroWallet.h +++ b/src/wallet/MoneroWallet.h @@ -55,6 +55,10 @@ #include "MoneroWalletModel.h" #include "wallet/wallet2.h" +#include +#include +#include + using namespace std; using namespace crypto; using namespace monero; @@ -225,15 +229,15 @@ namespace monero { */ shared_ptr getDaemonConnection() const; - bool getIsConnected(); + bool getIsConnected() const; - uint64_t getDaemonHeight(); + uint64_t getDaemonHeight() const; - uint64_t getDaemonTargetHeight(); + uint64_t getDaemonTargetHeight() const; - bool getIsDaemonSynced(); + bool getIsDaemonSynced() const; - bool getIsSynced(); + bool getIsSynced() const; /** * TODO @@ -1159,21 +1163,20 @@ namespace monero { boost::optional listener = boost::none; // wallet's external listener void initCommon(); - MoneroSyncResult syncAux(boost::optional startHeight, boost::optional endHeight, boost::optional listener); vector getSubaddressesAux(uint32_t accountIdx, vector subaddressIndices, const vector& transfers) const; - // sync thread management + // sync management mutable std::atomic isSynced; // whether or not wallet is synced mutable std::atomic isConnected; // cache connection status to avoid unecessary RPC calls boost::condition_variable syncCV; // to awaken sync threads - std::mutex syncMutex; // synchronize sync() and syncAsync() requests + boost::mutex syncMutex; // synchronize sync() and syncAsync() requests std::atomic rescanOnSync; // whether or not to rescan on sync std::atomic autoSyncEnabled; // whether or not auto sync is enabled - std::atomic autoSyncIntervalMillis; // auto sync loop inteval boost::thread autoSyncThread; // thread for auto sync loop - std::mutex autoSyncMutex; // synchronize auto sync loop + boost::mutex autoSyncMutex; // synchronize auto sync loop std::atomic autoSyncThreadDone; // whether or not auto sync loop is done (cannot be re-started) void autoSyncThreadFunc(); // function to run auto sync loop thread void doSync(); // internal synchronized sync function + MoneroSyncResult syncAux(boost::optional startHeight, boost::optional endHeight, boost::optional listener); // TODO: replace this with doSync() }; }