From 863e7fa836acde5f1183460425961f2be745776a Mon Sep 17 00:00:00 2001 From: Lee Clagett Date: Sat, 5 Apr 2025 23:38:58 -0400 Subject: [PATCH] Bug fixes, and improved status reporting --- src/backend.cpp | 32 ++++++++++++++++++++++++++----- src/backend.h | 1 + src/transaction_history.cpp | 2 -- src/wallet.cpp | 38 +++++++++++++++++++++++-------------- 4 files changed, 52 insertions(+), 21 deletions(-) diff --git a/src/backend.cpp b/src/backend.cpp index eb36ecf..c8c3664 100644 --- a/src/backend.cpp +++ b/src/backend.cpp @@ -520,7 +520,8 @@ namespace lwsf { namespace internal { namespace backend fee_mask(0), sync(), sync_listener(), - sync_refresh() + sync_refresh(), + passed_login(false) { primary.subaccounts[0].minor[0]; } @@ -546,10 +547,15 @@ namespace lwsf { namespace internal { namespace backend std::string wallet::get_spend_address(const rpc::address_meta& index) const { + const bool is_subaddress = (index.maj_i != 0 || index.min_i != 0); + const auto spend_public = get_spend_public(index); + const crypto::public_key view_public = is_subaddress ? + rct::rct2pk(rct::scalarmultKey(rct::pk2rct(spend_public), rct::sk2rct(primary.view.sec))) : primary.view.pub; + return cryptonote::get_account_address_as_str( get_net_type(), - (index.maj_i != 0 || index.min_i != 0), - cryptonote::account_public_address{get_spend_public(index), primary.view.pub} + is_subaddress, + cryptonote::account_public_address{spend_public, view_public} ); } @@ -592,6 +598,7 @@ namespace lwsf { namespace internal { namespace backend return response.error(); const boost::lock_guard lock{sync}; + passed_login = true; if (response->start_height) primary.restore_height = *response->start_height; } @@ -637,8 +644,21 @@ namespace lwsf { namespace internal { namespace backend return {}; } + const bool try_login = !passed_login; const rpc::login login{primary.address, primary.view.sec}; lock.unlock(); + + if (try_login) + { + const std::error_code failed_login = this->login(); + if (failed_login) + { + lock.lock(); + last_sync = now.time_since_epoch().count(); + return failed_login; + } + } + const auto txs_response = rpc::invoke(client, login); if (txs_response) { @@ -646,13 +666,15 @@ namespace lwsf { namespace internal { namespace backend outs_response = rpc::invoke(client, request); } + lock.lock(); + last_sync = now.time_since_epoch().count(); + passed_login = bool(txs_response) && bool(outs_response); // reset state + if (!txs_response) return txs_response.error(); if (!outs_response) return outs_response.error(); - lock.lock(); - last_sync = now.time_since_epoch().count(); const std::uint64_t orig_scan_height = primary.scan_height; const auto new_txes = merge_response(*this, *txs_response, *outs_response); diff --git a/src/backend.h b/src/backend.h index 26c78a6..584c685 100644 --- a/src/backend.h +++ b/src/backend.h @@ -208,6 +208,7 @@ namespace lwsf { namespace internal { namespace backend mutable boost::mutex sync; boost::mutex sync_listener; boost::mutex sync_refresh; + bool passed_login; wallet(); diff --git a/src/transaction_history.cpp b/src/transaction_history.cpp index a39c3e4..e7e9721 100644 --- a/src/transaction_history.cpp +++ b/src/transaction_history.cpp @@ -90,8 +90,6 @@ namespace lwsf { namespace internal void transaction_history::refresh() { - data_->refresh(false); - std::multimap> temp; { const boost::lock_guard lock{data_->sync}; diff --git a/src/wallet.cpp b/src/wallet.cpp index 5daed28..0070c6c 100644 --- a/src/wallet.cpp +++ b/src/wallet.cpp @@ -324,21 +324,23 @@ namespace lwsf { namespace internal return boost::chrono::nanoseconds{source.count()}; } - void load_wallet(backend::account& self, const crypto::secret_key& from, const Monero::NetworkType nettype, const bool generated_locally) + void load_wallet(backend::wallet& self, const crypto::secret_key& from, const Monero::NetworkType nettype, const bool generated_locally) { cryptonote::account_base base{}; base.generate(from, true); const auto& keys = base.get_keys(); - self.view.sec = keys.m_view_secret_key; - self.view.pub = keys.m_account_address.m_view_public_key; + self.primary.view.sec = keys.m_view_secret_key; + self.primary.view.pub = keys.m_account_address.m_view_public_key; - self.spend.sec = keys.m_spend_secret_key; - self.spend.pub = keys.m_account_address.m_spend_public_key; + self.primary.spend.sec = keys.m_spend_secret_key; + self.primary.spend.pub = keys.m_account_address.m_spend_public_key; - self.generated_locally = generated_locally; - self.type = nettype; + self.primary.generated_locally = generated_locally; + self.primary.type = nettype; + + self.primary.address = self.get_spend_address({0, 0}); } } // anonymous @@ -401,8 +403,12 @@ namespace lwsf { namespace internal // check while holding lock and before a wait call if (thread_state_ == state::stop) return; - - refresh_notify_.wait_for(lock, to_boost(config::refresh_interval)); + + const auto last_state = thread_state_; + refresh_notify_.wait_for( + lock, to_boost(config::refresh_interval), [this, last_state] () { + return mandatory_refresh_ || thread_state_ != last_state; + }); } } catch (const std::exception& e) @@ -485,7 +491,7 @@ namespace lwsf { namespace internal crypto::secret_key recovery; randombytes_buf(std::addressof(unwrap(unwrap(recovery))), sizeof(recovery)); - load_wallet(data_->primary, recovery, nettype, true); + load_wallet(*data_, recovery, nettype, true); } wallet::wallet(open, Monero::NetworkType nettype, std::string filename, std::string password, const std::uint64_t kdf_rounds) @@ -518,7 +524,7 @@ namespace lwsf { namespace internal if (file.empty()) file = try_load(filename_); - if (!file.empty()) + if (!filename_.empty() && !file.empty()) { encrypted_file contents{}; if (!(status_ = wire::msgpack::from_bytes(std::move(file), contents))) @@ -530,7 +536,7 @@ namespace lwsf { namespace internal { // lock not needed; data_ was created and unique to us if (nettype != data_->primary.type) - throw std::runtime_error{"Wallet file NetworkType does not match requested"}; + throw std::runtime_error{"Wallet file NetworkType does not match requested"}; } } else @@ -582,7 +588,7 @@ namespace lwsf { namespace internal if (!seed_offset.empty()) recovery = cryptonote::decrypt_key(recovery, seed_offset); - load_wallet(data_->primary, recovery, nettype, false); + load_wallet(*data_, recovery, nettype, false); } @@ -905,7 +911,11 @@ namespace lwsf { namespace internal Monero::Wallet::ConnectionStatus wallet::connected() const { - return data_->client.is_connected() ? + if (!data_->client.is_connected()) + return ConnectionStatus_Disconnected; + + const boost::lock_guard lock{data_->sync}; + return data_->passed_login ? ConnectionStatus_Connected : ConnectionStatus_Disconnected; }