diff options
-rw-r--r-- | contrib/epee/include/file_io_utils.h | 25 | ||||
-rw-r--r-- | contrib/epee/include/string_tools.h | 35 | ||||
-rw-r--r-- | src/common/util.cpp | 98 | ||||
-rw-r--r-- | src/common/util.h | 14 | ||||
-rw-r--r-- | src/cryptonote_core/blockchain.cpp | 2 | ||||
-rw-r--r-- | src/wallet/api/address_book.h | 14 | ||||
-rw-r--r-- | src/wallet/api/pending_transaction.h | 26 | ||||
-rw-r--r-- | src/wallet/api/subaddress.h | 8 | ||||
-rw-r--r-- | src/wallet/api/transaction_info.h | 30 | ||||
-rw-r--r-- | src/wallet/api/unsigned_transaction.h | 23 | ||||
-rw-r--r-- | src/wallet/api/wallet.cpp | 3 | ||||
-rw-r--r-- | src/wallet/api/wallet.h | 184 | ||||
-rw-r--r-- | src/wallet/api/wallet_manager.h | 44 | ||||
-rw-r--r-- | src/wallet/wallet2.cpp | 8 | ||||
-rw-r--r-- | src/wallet/wallet2.h | 1 | ||||
-rw-r--r-- | src/wallet/wallet_rpc_server_commands_defs.h | 6 |
16 files changed, 324 insertions, 197 deletions
diff --git a/contrib/epee/include/file_io_utils.h b/contrib/epee/include/file_io_utils.h index 4434f7383..25f8c648b 100644 --- a/contrib/epee/include/file_io_utils.h +++ b/contrib/epee/include/file_io_utils.h @@ -33,6 +33,7 @@ #include <boost/filesystem/operations.hpp> #ifdef WIN32 #include <windows.h> +#include "string_tools.h" #endif // On Windows there is a problem with non-ASCII characters in path and file names @@ -72,11 +73,9 @@ namespace file_io_utils bool save_string_to_file(const std::string& path_to_file, const std::string& str) { #ifdef WIN32 - WCHAR wide_path[1000]; - int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000); - if (chars == 0) - return false; - HANDLE file_handle = CreateFileW(wide_path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + std::wstring wide_path; + try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; } + HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) return false; DWORD bytes_written; @@ -131,11 +130,9 @@ namespace file_io_utils bool load_file_to_string(const std::string& path_to_file, std::string& target_str, size_t max_size = 1000000000) { #ifdef WIN32 - WCHAR wide_path[1000]; - int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000); - if (chars == 0) - return false; - HANDLE file_handle = CreateFileW(wide_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + std::wstring wide_path; + try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; } + HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) return false; DWORD file_size = GetFileSize(file_handle, NULL); @@ -202,11 +199,9 @@ namespace file_io_utils bool get_file_size(const std::string& path_to_file, uint64_t &size) { #ifdef WIN32 - WCHAR wide_path[1000]; - int chars = MultiByteToWideChar(CP_UTF8, 0, path_to_file.c_str(), path_to_file.size() + 1, wide_path, 1000); - if (chars == 0) - return false; - HANDLE file_handle = CreateFileW(wide_path, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + std::wstring wide_path; + try { wide_path = string_tools::utf8_to_utf16(path_to_file); } catch (...) { return false; } + HANDLE file_handle = CreateFileW(wide_path.c_str(), GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (file_handle == INVALID_HANDLE_VALUE) return false; LARGE_INTEGER file_size; diff --git a/contrib/epee/include/string_tools.h b/contrib/epee/include/string_tools.h index 63705e401..8d8603076 100644 --- a/contrib/epee/include/string_tools.h +++ b/contrib/epee/include/string_tools.h @@ -381,6 +381,41 @@ POP_WARNINGS res = str.substr(0, pos); return res; } + //---------------------------------------------------------------------------- +#ifdef _WIN32 + inline std::wstring utf8_to_utf16(const std::string& str) + { + if (str.empty()) + return {}; + int wstr_size = MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), NULL, 0); + if (wstr_size == 0) + { + throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message()); + } + std::wstring wstr(wstr_size, wchar_t{}); + if (!MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), &wstr[0], wstr_size)) + { + throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message()); + } + return wstr; + } + inline std::string utf16_to_utf8(const std::wstring& wstr) + { + if (wstr.empty()) + return {}; + int str_size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), NULL, 0, NULL, NULL); + if (str_size == 0) + { + throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message()); + } + std::string str(str_size, char{}); + if (!WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), &str[0], str_size, NULL, NULL)) + { + throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message()); + } + return str; + } +#endif } } #endif //_STRING_TOOLS_H_ diff --git a/src/common/util.cpp b/src/common/util.cpp index 329352e94..7d9d7b408 100644 --- a/src/common/util.cpp +++ b/src/common/util.cpp @@ -195,6 +195,73 @@ namespace tools catch (...) {} } + file_locker::file_locker(const std::string &filename) + { +#ifdef WIN32 + m_fd = INVALID_HANDLE_VALUE; + std::wstring filename_wide; + try + { + filename_wide = string_tools::utf8_to_utf16(filename); + } + catch (const std::exception &e) + { + MERROR("Failed to convert path \"" << filename << "\" to UTF-16: " << e.what()); + return; + } + m_fd = CreateFileW(filename_wide.c_str(), GENERIC_READ, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (m_fd != INVALID_HANDLE_VALUE) + { + OVERLAPPED ov; + memset(&ov, 0, sizeof(ov)); + if (!LockFileEx(m_fd, LOCKFILE_FAIL_IMMEDIATELY | LOCKFILE_EXCLUSIVE_LOCK, 0, 1, 0, &ov)) + { + MERROR("Failed to lock " << filename << ": " << std::error_code(GetLastError(), std::system_category())); + CloseHandle(m_fd); + m_fd = INVALID_HANDLE_VALUE; + } + } + else + { + MERROR("Failed to open " << filename << ": " << std::error_code(GetLastError(), std::system_category())); + } +#else + m_fd = open(filename.c_str(), O_RDONLY | O_CREAT, 0666); + if (m_fd != -1) + { + if (flock(m_fd, LOCK_EX | LOCK_NB) == -1) + { + MERROR("Failed to lock " << filename << ": " << std::strerror(errno)); + close(m_fd); + m_fd = -1; + } + } + else + { + MERROR("Failed to open " << filename << ": " << std::strerror(errno)); + } +#endif + } + file_locker::~file_locker() + { + if (locked()) + { +#ifdef WIN32 + CloseHandle(m_fd); +#else + close(m_fd); +#endif + } + } + bool file_locker::locked() const + { +#ifdef WIN32 + return m_fd != INVALID_HANDLE_VALUE; +#else + return m_fd != -1; +#endif + } + #ifdef WIN32 std::string get_windows_version_display_string() { @@ -451,10 +518,15 @@ std::string get_nix_version_display_string() if (SHGetSpecialFolderPathW(NULL, psz_path, nfolder, iscreate)) { - int size_needed = WideCharToMultiByte(CP_UTF8, 0, psz_path, wcslen(psz_path), NULL, 0, NULL, NULL); - std::string folder_name(size_needed, 0); - WideCharToMultiByte(CP_UTF8, 0, psz_path, wcslen(psz_path), &folder_name[0], size_needed, NULL, NULL); - return folder_name; + try + { + return string_tools::utf16_to_utf8(psz_path); + } + catch (const std::exception &e) + { + MERROR("utf16_to_utf8 failed: " << e.what()); + return ""; + } } LOG_ERROR("SHGetSpecialFolderPathW() failed, could not obtain requested path."); @@ -515,18 +587,20 @@ std::string get_nix_version_display_string() int code; #if defined(WIN32) // Maximizing chances for success - WCHAR wide_replacement_name[1000]; - MultiByteToWideChar(CP_UTF8, 0, replacement_name.c_str(), replacement_name.size() + 1, wide_replacement_name, 1000); - WCHAR wide_replaced_name[1000]; - MultiByteToWideChar(CP_UTF8, 0, replaced_name.c_str(), replaced_name.size() + 1, wide_replaced_name, 1000); - - DWORD attributes = ::GetFileAttributesW(wide_replaced_name); + std::wstring wide_replacement_name; + try { wide_replacement_name = string_tools::utf8_to_utf16(replacement_name); } + catch (...) { return std::error_code(GetLastError(), std::system_category()); } + std::wstring wide_replaced_name; + try { wide_replaced_name = string_tools::utf8_to_utf16(replaced_name); } + catch (...) { return std::error_code(GetLastError(), std::system_category()); } + + DWORD attributes = ::GetFileAttributesW(wide_replaced_name.c_str()); if (INVALID_FILE_ATTRIBUTES != attributes) { - ::SetFileAttributesW(wide_replaced_name, attributes & (~FILE_ATTRIBUTE_READONLY)); + ::SetFileAttributesW(wide_replaced_name.c_str(), attributes & (~FILE_ATTRIBUTE_READONLY)); } - bool ok = 0 != ::MoveFileExW(wide_replacement_name, wide_replaced_name, MOVEFILE_REPLACE_EXISTING); + bool ok = 0 != ::MoveFileExW(wide_replacement_name.c_str(), wide_replaced_name.c_str(), MOVEFILE_REPLACE_EXISTING); code = ok ? 0 : static_cast<int>(::GetLastError()); #else bool ok = 0 == std::rename(replacement_name.c_str(), replaced_name.c_str()); diff --git a/src/common/util.h b/src/common/util.h index dc426830b..a57a85fee 100644 --- a/src/common/util.h +++ b/src/common/util.h @@ -91,6 +91,20 @@ namespace tools const std::string& filename() const noexcept { return m_filename; } }; + class file_locker + { + public: + file_locker(const std::string &filename); + ~file_locker(); + bool locked() const; + private: +#ifdef WIN32 + HANDLE m_fd; +#else + int m_fd; +#endif + }; + /*! \brief Returns the default data directory. * * \details Windows < Vista: C:\\Documents and Settings\\Username\\Application Data\\CRYPTONOTE_NAME diff --git a/src/cryptonote_core/blockchain.cpp b/src/cryptonote_core/blockchain.cpp index fb88a13cb..73ce98366 100644 --- a/src/cryptonote_core/blockchain.cpp +++ b/src/cryptonote_core/blockchain.cpp @@ -2745,7 +2745,7 @@ bool Blockchain::check_tx_inputs(transaction& tx, tx_verification_context &tvc, tools::threadpool& tpool = tools::threadpool::getInstance(); tools::threadpool::waiter waiter; - const auto waiter_guard = epee::misc_utils::create_scope_leave_handler([&]() { waiter.wait(); }); + const auto waiter_guard = epee::misc_utils::create_scope_leave_handler([&]() { waiter.wait(&tpool); }); int threads = tpool.get_max_concurrency(); for (const auto& txin : tx.vin) diff --git a/src/wallet/api/address_book.h b/src/wallet/api/address_book.h index 7d9200550..f4ca68efd 100644 --- a/src/wallet/api/address_book.h +++ b/src/wallet/api/address_book.h @@ -42,16 +42,16 @@ public: ~AddressBookImpl(); // Fetches addresses from Wallet2 - void refresh(); - std::vector<AddressBookRow*> getAll() const; - bool addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description); - bool deleteRow(std::size_t rowId); + void refresh() override; + std::vector<AddressBookRow*> getAll() const override; + bool addRow(const std::string &dst_addr , const std::string &payment_id, const std::string &description) override; + bool deleteRow(std::size_t rowId) override; // Error codes. See AddressBook:ErrorCode enum in wallet2_api.h - std::string errorString() const {return m_errorString;} - int errorCode() const {return m_errorCode;} + std::string errorString() const override {return m_errorString;} + int errorCode() const override {return m_errorCode;} - int lookupPaymentID(const std::string &payment_id) const; + int lookupPaymentID(const std::string &payment_id) const override; private: void clearRows(); diff --git a/src/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h index 4f963c134..50b9f07ef 100644 --- a/src/wallet/api/pending_transaction.h +++ b/src/wallet/api/pending_transaction.h @@ -43,21 +43,21 @@ class PendingTransactionImpl : public PendingTransaction public: PendingTransactionImpl(WalletImpl &wallet); ~PendingTransactionImpl(); - int status() const; - std::string errorString() const; - bool commit(const std::string &filename = "", bool overwrite = false); - uint64_t amount() const; - uint64_t dust() const; - uint64_t fee() const; - std::vector<std::string> txid() const; - uint64_t txCount() const; - std::vector<uint32_t> subaddrAccount() const; - std::vector<std::set<uint32_t>> subaddrIndices() const; + int status() const override; + std::string errorString() const override; + bool commit(const std::string &filename = "", bool overwrite = false) override; + uint64_t amount() const override; + uint64_t dust() const override; + uint64_t fee() const override; + std::vector<std::string> txid() const override; + uint64_t txCount() const override; + std::vector<uint32_t> subaddrAccount() const override; + std::vector<std::set<uint32_t>> subaddrIndices() const override; // TODO: continue with interface; - std::string multisigSignData(); - void signMultisigTx(); - std::vector<std::string> signersKeys() const; + std::string multisigSignData() override; + void signMultisigTx() override; + std::vector<std::string> signersKeys() const override; private: friend class WalletImpl; diff --git a/src/wallet/api/subaddress.h b/src/wallet/api/subaddress.h index 3f9e37ac8..f3db7d97b 100644 --- a/src/wallet/api/subaddress.h +++ b/src/wallet/api/subaddress.h @@ -40,10 +40,10 @@ public: ~SubaddressImpl(); // Fetches addresses from Wallet2 - void refresh(uint32_t accountIndex); - std::vector<SubaddressRow*> getAll() const; - void addRow(uint32_t accountIndex, const std::string &label); - void setLabel(uint32_t accountIndex, uint32_t addressIndex, const std::string &label); + void refresh(uint32_t accountIndex) override; + std::vector<SubaddressRow*> getAll() const override; + void addRow(uint32_t accountIndex, const std::string &label) override; + void setLabel(uint32_t accountIndex, uint32_t addressIndex, const std::string &label) override; private: void clearRows(); diff --git a/src/wallet/api/transaction_info.h b/src/wallet/api/transaction_info.h index 5df9a44ef..37e0445d9 100644 --- a/src/wallet/api/transaction_info.h +++ b/src/wallet/api/transaction_info.h @@ -42,24 +42,24 @@ public: TransactionInfoImpl(); ~TransactionInfoImpl(); //! in/out - virtual int direction() const; + virtual int direction() const override; //! true if hold - virtual bool isPending() const; - virtual bool isFailed() const; - virtual uint64_t amount() const; + virtual bool isPending() const override; + virtual bool isFailed() const override; + virtual uint64_t amount() const override; //! always 0 for incoming txes - virtual uint64_t fee() const; - virtual uint64_t blockHeight() const; - virtual std::set<uint32_t> subaddrIndex() const; - virtual uint32_t subaddrAccount() const; - virtual std::string label() const; + virtual uint64_t fee() const override; + virtual uint64_t blockHeight() const override; + virtual std::set<uint32_t> subaddrIndex() const override; + virtual uint32_t subaddrAccount() const override; + virtual std::string label() const override; - virtual std::string hash() const; - virtual std::time_t timestamp() const; - virtual std::string paymentId() const; - virtual const std::vector<Transfer> &transfers() const; - virtual uint64_t confirmations() const; - virtual uint64_t unlockTime() const; + virtual std::string hash() const override; + virtual std::time_t timestamp() const override; + virtual std::string paymentId() const override; + virtual const std::vector<Transfer> &transfers() const override; + virtual uint64_t confirmations() const override; + virtual uint64_t unlockTime() const override; private: int m_direction; diff --git a/src/wallet/api/unsigned_transaction.h b/src/wallet/api/unsigned_transaction.h index a35630535..8a3330014 100644 --- a/src/wallet/api/unsigned_transaction.h +++ b/src/wallet/api/unsigned_transaction.h @@ -43,19 +43,18 @@ class UnsignedTransactionImpl : public UnsignedTransaction public: UnsignedTransactionImpl(WalletImpl &wallet); ~UnsignedTransactionImpl(); - int status() const; - std::string errorString() const; - std::vector<uint64_t> amount() const; - std::vector<uint64_t> dust() const; - std::vector<uint64_t> fee() const; - std::vector<uint64_t> mixin() const; - std::vector<std::string> paymentId() const; - std::vector<std::string> recipientAddress() const; - uint64_t txCount() const; + int status() const override; + std::string errorString() const override; + std::vector<uint64_t> amount() const override; + std::vector<uint64_t> fee() const override; + std::vector<uint64_t> mixin() const override; + std::vector<std::string> paymentId() const override; + std::vector<std::string> recipientAddress() const override; + uint64_t txCount() const override; // sign txs and save to file - bool sign(const std::string &signedFileName); - std::string confirmationMessage() const {return m_confirmationMessage;} - uint64_t minMixinCount() const; + bool sign(const std::string &signedFileName) override; + std::string confirmationMessage() const override {return m_confirmationMessage;} + uint64_t minMixinCount() const override; private: // Callback function to check all loaded tx's and generate confirmationMessage diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp index c7dbd29e4..3f6bfec9e 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -721,6 +721,7 @@ bool WalletImpl::close(bool store) LOG_PRINT_L1("Calling wallet::stop..."); m_wallet->stop(); LOG_PRINT_L1("wallet::stop done"); + m_wallet->deinit(); result = true; clearStatus(); } catch (const std::exception &e) { @@ -1965,7 +1966,7 @@ void WalletImpl::doRefresh() // Syncing daemon and refreshing wallet simultaneously is very resource intensive. // Disable refresh if wallet is disconnected or daemon isn't synced. if (m_wallet->light_wallet() || daemonSynced()) { - m_wallet->refresh(); + m_wallet->refresh(trustedDaemon()); if (!m_synchronized) { m_synchronized = true; } diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h index 08232cafd..eefb2fe94 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h @@ -57,7 +57,7 @@ public: bool create(const std::string &path, const std::string &password, const std::string &language); bool createWatchOnly(const std::string &path, const std::string &password, - const std::string &language) const; + const std::string &language) const override; bool open(const std::string &path, const std::string &password); bool recover(const std::string &path,const std::string &password, const std::string &seed); @@ -80,58 +80,58 @@ public: const std::string &password, const std::string &device_name); bool close(bool store = true); - std::string seed() const; - std::string getSeedLanguage() const; - void setSeedLanguage(const std::string &arg); + std::string seed() const override; + std::string getSeedLanguage() const override; + void setSeedLanguage(const std::string &arg) override; // void setListener(Listener *) {} - int status() const; - std::string errorString() const; + int status() const override; + std::string errorString() const override; void statusWithErrorString(int& status, std::string& errorString) const override; - bool setPassword(const std::string &password); - std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const; - std::string integratedAddress(const std::string &payment_id) const; - std::string secretViewKey() const; - std::string publicViewKey() const; - std::string secretSpendKey() const; - std::string publicSpendKey() const; - std::string publicMultisigSignerKey() const; - std::string path() const; - bool store(const std::string &path); - std::string filename() const; - std::string keysFilename() const; - bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, const std::string &daemon_username = "", const std::string &daemon_password = "", bool use_ssl = false, bool lightWallet = false); - bool connectToDaemon(); - ConnectionStatus connected() const; - void setTrustedDaemon(bool arg); - bool trustedDaemon() const; - uint64_t balance(uint32_t accountIndex = 0) const; - uint64_t unlockedBalance(uint32_t accountIndex = 0) const; - uint64_t blockChainHeight() const; - uint64_t approximateBlockChainHeight() const; - uint64_t daemonBlockChainHeight() const; - uint64_t daemonBlockChainTargetHeight() const; - bool synchronized() const; - bool refresh(); - void refreshAsync(); - void setAutoRefreshInterval(int millis); - int autoRefreshInterval() const; - void setRefreshFromBlockHeight(uint64_t refresh_from_block_height); - uint64_t getRefreshFromBlockHeight() const { return m_wallet->get_refresh_from_block_height(); }; - void setRecoveringFromSeed(bool recoveringFromSeed); + bool setPassword(const std::string &password) override; + std::string address(uint32_t accountIndex = 0, uint32_t addressIndex = 0) const override; + std::string integratedAddress(const std::string &payment_id) const override; + std::string secretViewKey() const override; + std::string publicViewKey() const override; + std::string secretSpendKey() const override; + std::string publicSpendKey() const override; + std::string publicMultisigSignerKey() const override; + std::string path() const override; + bool store(const std::string &path) override; + std::string filename() const override; + std::string keysFilename() const override; + bool init(const std::string &daemon_address, uint64_t upper_transaction_size_limit = 0, const std::string &daemon_username = "", const std::string &daemon_password = "", bool use_ssl = false, bool lightWallet = false) override; + bool connectToDaemon() override; + ConnectionStatus connected() const override; + void setTrustedDaemon(bool arg) override; + bool trustedDaemon() const override; + uint64_t balance(uint32_t accountIndex = 0) const override; + uint64_t unlockedBalance(uint32_t accountIndex = 0) const override; + uint64_t blockChainHeight() const override; + uint64_t approximateBlockChainHeight() const override; + uint64_t daemonBlockChainHeight() const override; + uint64_t daemonBlockChainTargetHeight() const override; + bool synchronized() const override; + bool refresh() override; + void refreshAsync() override; + void setAutoRefreshInterval(int millis) override; + int autoRefreshInterval() const override; + void setRefreshFromBlockHeight(uint64_t refresh_from_block_height) override; + uint64_t getRefreshFromBlockHeight() const override { return m_wallet->get_refresh_from_block_height(); }; + void setRecoveringFromSeed(bool recoveringFromSeed) override; void setRecoveringFromDevice(bool recoveringFromDevice) override; void setSubaddressLookahead(uint32_t major, uint32_t minor) override; - bool watchOnly() const; - bool rescanSpent(); - NetworkType nettype() const {return static_cast<NetworkType>(m_wallet->nettype());} - void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const; - bool useForkRules(uint8_t version, int64_t early_blocks) const; - - void addSubaddressAccount(const std::string& label); - size_t numSubaddressAccounts() const; - size_t numSubaddresses(uint32_t accountIndex) const; - void addSubaddress(uint32_t accountIndex, const std::string& label); - std::string getSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex) const; - void setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex, const std::string &label); + bool watchOnly() const override; + bool rescanSpent() override; + NetworkType nettype() const override {return static_cast<NetworkType>(m_wallet->nettype());} + void hardForkInfo(uint8_t &version, uint64_t &earliest_height) const override; + bool useForkRules(uint8_t version, int64_t early_blocks) const override; + + void addSubaddressAccount(const std::string& label) override; + size_t numSubaddressAccounts() const override; + size_t numSubaddresses(uint32_t accountIndex) const override; + void addSubaddress(uint32_t accountIndex, const std::string& label) override; + std::string getSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex) const override; + void setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex, const std::string &label) override; MultisigState multisig() const override; std::string getMultisigInfo() const override; @@ -145,49 +145,49 @@ public: optional<uint64_t> amount, uint32_t mixin_count, PendingTransaction::Priority priority = PendingTransaction::Priority_Low, uint32_t subaddr_account = 0, - std::set<uint32_t> subaddr_indices = {}); - virtual PendingTransaction * createSweepUnmixableTransaction(); - bool submitTransaction(const std::string &fileName); - virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename); - bool exportKeyImages(const std::string &filename); - bool importKeyImages(const std::string &filename); - - virtual void disposeTransaction(PendingTransaction * t); - virtual TransactionHistory * history(); - virtual AddressBook * addressBook(); - virtual Subaddress * subaddress(); - virtual SubaddressAccount * subaddressAccount(); - virtual void setListener(WalletListener * l); - virtual uint32_t defaultMixin() const; - virtual void setDefaultMixin(uint32_t arg); - virtual bool setUserNote(const std::string &txid, const std::string ¬e); - virtual std::string getUserNote(const std::string &txid) const; - virtual std::string getTxKey(const std::string &txid) const; - virtual bool checkTxKey(const std::string &txid, std::string tx_key, const std::string &address, uint64_t &received, bool &in_pool, uint64_t &confirmations); - virtual std::string getTxProof(const std::string &txid, const std::string &address, const std::string &message) const; - virtual bool checkTxProof(const std::string &txid, const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &received, bool &in_pool, uint64_t &confirmations); - virtual std::string getSpendProof(const std::string &txid, const std::string &message) const; - virtual bool checkSpendProof(const std::string &txid, const std::string &message, const std::string &signature, bool &good) const; - virtual std::string getReserveProof(bool all, uint32_t account_index, uint64_t amount, const std::string &message) const; - virtual bool checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const; - virtual std::string signMessage(const std::string &message); - virtual bool verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const; - virtual std::string signMultisigParticipant(const std::string &message) const; - virtual bool verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const; - virtual void startRefresh(); - virtual void pauseRefresh(); - virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error); - virtual std::string getDefaultDataDir() const; - virtual bool lightWalletLogin(bool &isNewWallet) const; - virtual bool lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status); - virtual bool blackballOutputs(const std::vector<std::string> &pubkeys, bool add); - virtual bool unblackballOutput(const std::string &pubkey); - virtual bool getRing(const std::string &key_image, std::vector<uint64_t> &ring) const; - virtual bool getRings(const std::string &txid, std::vector<std::pair<std::string, std::vector<uint64_t>>> &rings) const; - virtual bool setRing(const std::string &key_image, const std::vector<uint64_t> &ring, bool relative); - virtual void segregatePreForkOutputs(bool segregate); - virtual void segregationHeight(uint64_t height); - virtual void keyReuseMitigation2(bool mitigation); + std::set<uint32_t> subaddr_indices = {}) override; + virtual PendingTransaction * createSweepUnmixableTransaction() override; + bool submitTransaction(const std::string &fileName) override; + virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override; + bool exportKeyImages(const std::string &filename) override; + bool importKeyImages(const std::string &filename) override; + + virtual void disposeTransaction(PendingTransaction * t) override; + virtual TransactionHistory * history() override; + virtual AddressBook * addressBook() override; + virtual Subaddress * subaddress() override; + virtual SubaddressAccount * subaddressAccount() override; + virtual void setListener(WalletListener * l) override; + virtual uint32_t defaultMixin() const override; + virtual void setDefaultMixin(uint32_t arg) override; + virtual bool setUserNote(const std::string &txid, const std::string ¬e) override; + virtual std::string getUserNote(const std::string &txid) const override; + virtual std::string getTxKey(const std::string &txid) const override; + virtual bool checkTxKey(const std::string &txid, std::string tx_key, const std::string &address, uint64_t &received, bool &in_pool, uint64_t &confirmations) override; + virtual std::string getTxProof(const std::string &txid, const std::string &address, const std::string &message) const override; + virtual bool checkTxProof(const std::string &txid, const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &received, bool &in_pool, uint64_t &confirmations) override; + virtual std::string getSpendProof(const std::string &txid, const std::string &message) const override; + virtual bool checkSpendProof(const std::string &txid, const std::string &message, const std::string &signature, bool &good) const override; + virtual std::string getReserveProof(bool all, uint32_t account_index, uint64_t amount, const std::string &message) const override; + virtual bool checkReserveProof(const std::string &address, const std::string &message, const std::string &signature, bool &good, uint64_t &total, uint64_t &spent) const override; + virtual std::string signMessage(const std::string &message) override; + virtual bool verifySignedMessage(const std::string &message, const std::string &address, const std::string &signature) const override; + virtual std::string signMultisigParticipant(const std::string &message) const override; + virtual bool verifyMessageWithPublicKey(const std::string &message, const std::string &publicKey, const std::string &signature) const override; + virtual void startRefresh() override; + virtual void pauseRefresh() override; + virtual bool parse_uri(const std::string &uri, std::string &address, std::string &payment_id, uint64_t &amount, std::string &tx_description, std::string &recipient_name, std::vector<std::string> &unknown_parameters, std::string &error) override; + virtual std::string getDefaultDataDir() const override; + virtual bool lightWalletLogin(bool &isNewWallet) const override; + virtual bool lightWalletImportWalletRequest(std::string &payment_id, uint64_t &fee, bool &new_request, bool &request_fulfilled, std::string &payment_address, std::string &status) override; + virtual bool blackballOutputs(const std::vector<std::string> &pubkeys, bool add) override; + virtual bool unblackballOutput(const std::string &pubkey) override; + virtual bool getRing(const std::string &key_image, std::vector<uint64_t> &ring) const override; + virtual bool getRings(const std::string &txid, std::vector<std::pair<std::string, std::vector<uint64_t>>> &rings) const override; + virtual bool setRing(const std::string &key_image, const std::vector<uint64_t> &ring, bool relative) override; + virtual void segregatePreForkOutputs(bool segregate) override; + virtual void segregationHeight(uint64_t height) override; + virtual void keyReuseMitigation2(bool mitigation) override; private: void clearStatus() const; diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h index 19aad9ee3..656a7142c 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h @@ -39,13 +39,13 @@ class WalletManagerImpl : public WalletManager { public: Wallet * createWallet(const std::string &path, const std::string &password, - const std::string &language, NetworkType nettype); - Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype); + const std::string &language, NetworkType nettype) override; + Wallet * openWallet(const std::string &path, const std::string &password, NetworkType nettype) override; virtual Wallet * recoveryWallet(const std::string &path, const std::string &password, const std::string &mnemonic, NetworkType nettype, - uint64_t restoreHeight); + uint64_t restoreHeight) override; virtual Wallet * createWalletFromKeys(const std::string &path, const std::string &password, const std::string &language, @@ -53,9 +53,9 @@ public: uint64_t restoreHeight, const std::string &addressString, const std::string &viewKeyString, - const std::string &spendKeyString = ""); + const std::string &spendKeyString = "") override; // next two methods are deprecated - use the above version which allow setting of a password - virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight); + virtual Wallet * recoveryWallet(const std::string &path, const std::string &mnemonic, NetworkType nettype, uint64_t restoreHeight) override; // deprecated: use createWalletFromKeys(..., password, ...) instead virtual Wallet * createWalletFromKeys(const std::string &path, const std::string &language, @@ -63,29 +63,29 @@ public: uint64_t restoreHeight, const std::string &addressString, const std::string &viewKeyString, - const std::string &spendKeyString = ""); + const std::string &spendKeyString = "") override; virtual Wallet * createWalletFromDevice(const std::string &path, const std::string &password, NetworkType nettype, const std::string &deviceName, uint64_t restoreHeight = 0, const std::string &subaddressLookahead = "") override; - virtual bool closeWallet(Wallet *wallet, bool store = true); - bool walletExists(const std::string &path); - bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const; - std::vector<std::string> findWallets(const std::string &path); - std::string errorString() const; - void setDaemonAddress(const std::string &address); - bool connected(uint32_t *version = NULL); - uint64_t blockchainHeight(); - uint64_t blockchainTargetHeight(); - uint64_t networkDifficulty(); - double miningHashRate(); - uint64_t blockTarget(); - bool isMining(); - bool startMining(const std::string &address, uint32_t threads = 1, bool background_mining = false, bool ignore_battery = true); - bool stopMining(); - std::string resolveOpenAlias(const std::string &address, bool &dnssec_valid) const; + virtual bool closeWallet(Wallet *wallet, bool store = true) override; + bool walletExists(const std::string &path) override; + bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key) const override; + std::vector<std::string> findWallets(const std::string &path) override; + std::string errorString() const override; + void setDaemonAddress(const std::string &address) override; + bool connected(uint32_t *version = NULL) override; + uint64_t blockchainHeight() override; + uint64_t blockchainTargetHeight() override; + uint64_t networkDifficulty() override; + double miningHashRate() override; + uint64_t blockTarget() override; + bool isMining() override; + bool startMining(const std::string &address, uint32_t threads = 1, bool background_mining = false, bool ignore_battery = true) override; + bool stopMining() override; + std::string resolveOpenAlias(const std::string &address, bool &dnssec_valid) const override; private: WalletManagerImpl() {} diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index e5e331797..1a1537e62 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -2636,6 +2636,7 @@ void wallet2::detach_blockchain(uint64_t height) bool wallet2::deinit() { m_is_initialized=false; + m_keys_file_locker.reset(); return true; } //---------------------------------------------------------------------------------------------------- @@ -2802,10 +2803,12 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable crypto::chacha20(account_data.data(), account_data.size(), key, keys_file_data.iv, &cipher[0]); keys_file_data.account_data = cipher; + m_keys_file_locker.reset(); std::string buf; r = ::serialization::dump_binary(keys_file_data, buf); r = r && epee::file_io_utils::save_string_to_file(keys_file_name, buf); //and never touch wallet_keys_file again, only read CHECK_AND_ASSERT_MES(r, false, "failed to generate wallet keys file " << keys_file_name); + m_keys_file_locker.reset(new tools::file_locker(m_keys_file)); return true; } @@ -3935,12 +3938,17 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass boost::system::error_code e; bool exists = boost::filesystem::exists(m_keys_file, e); THROW_WALLET_EXCEPTION_IF(e || !exists, error::file_not_found, m_keys_file); + m_keys_file_locker.reset(new tools::file_locker(m_keys_file)); + THROW_WALLET_EXCEPTION_IF(!m_keys_file_locker->locked(), error::wallet_internal_error, "internal error: \"" + m_keys_file + "\" is opened by another wallet program"); + // this temporary unlocking is necessary for Windows (otherwise the file couldn't be loaded). + m_keys_file_locker.reset(); if (!load_keys(m_keys_file, password)) { THROW_WALLET_EXCEPTION_IF(true, error::file_read_error, m_keys_file); } LOG_PRINT_L0("Loaded wallet keys file, with public address: " << m_account.get_public_address_str(m_nettype)); + m_keys_file_locker.reset(new tools::file_locker(m_keys_file)); //keys loaded ok! //try to load wallet file. but even if we failed, it is not big problem diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 705933979..d33d8258b 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1308,6 +1308,7 @@ namespace tools boost::optional<crypto::chacha_key> m_ringdb_key; uint64_t m_last_block_reward; + std::unique_ptr<tools::file_locker> m_keys_file_locker; }; } BOOST_CLASS_VERSION(tools::wallet2, 25) diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index aa61640a3..1bd572add 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -1195,7 +1195,7 @@ namespace wallet_rpc std::string address; bool double_spend_seen; uint64_t confirmations; - uint64_t suggested_confirmation_threshold; + uint64_t suggested_confirmations_threshold; BEGIN_KV_SERIALIZE_MAP() KV_SERIALIZE(txid); @@ -1211,8 +1211,8 @@ namespace wallet_rpc KV_SERIALIZE(subaddr_index); KV_SERIALIZE(address); KV_SERIALIZE(double_spend_seen) - KV_SERIALIZE_OPT(confirmations, 0) - KV_SERIALIZE_OPT(suggested_confirmation_threshold, 0) + KV_SERIALIZE_OPT(confirmations, (uint64_t)0) + KV_SERIALIZE_OPT(suggested_confirmations_threshold, (uint64_t)0) END_KV_SERIALIZE_MAP() }; |