diff --git a/patches/wownero/0001-polyseed.patch b/patches/monero/0001-polyseed.patch similarity index 92% rename from patches/wownero/0001-polyseed.patch rename to patches/monero/0001-polyseed.patch index 56445d8..855a2dc 100644 --- a/patches/wownero/0001-polyseed.patch +++ b/patches/monero/0001-polyseed.patch @@ -1,7 +1,7 @@ -From d2a438a3c5c2db85c897b7dd26d41c653c7a83e3 Mon Sep 17 00:00:00 2001 +From bf347a3c80f0e0647176752867a54ae9ecedb580 Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto -Date: Tue, 26 Mar 2024 08:19:23 +0100 -Subject: [PATCH] polyseed support +Date: Tue, 12 Mar 2024 09:42:37 +0100 +Subject: [PATCH 1/8] polyseed --- .github/workflows/build.yml | 4 +- @@ -54,36 +54,36 @@ index 4c1e381c0..70bea03b3 100644 test-ubuntu: needs: build-ubuntu diff --git a/.gitmodules b/.gitmodules -index 74571d5ee..86009b6b6 100644 +index 721cce3b4..73a23fb35 100644 --- a/.gitmodules +++ b/.gitmodules -@@ -12,6 +12,12 @@ - path = external/supercop - url = https://github.com/monero-project/supercop - branch = monero +@@ -10,6 +10,12 @@ + [submodule "external/randomx"] + path = external/randomx + url = https://github.com/tevador/RandomX +[submodule "external/utf8proc"] + path = external/utf8proc + url = https://github.com/JuliaStrings/utf8proc.git +[submodule "external/polyseed"] + path = external/polyseed + url = https://github.com/tevador/polyseed.git - [submodule "external/randomwow"] - path = external/randomwow - url = https://git.wownero.com/wownero/RandomWOW + [submodule "external/supercop"] + path = external/supercop + url = https://github.com/monero-project/supercop diff --git a/CMakeLists.txt b/CMakeLists.txt -index 20829bc30..2dd427d3d 100644 +index 8fb03ba1f..63b8c5079 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -370,6 +370,8 @@ if(NOT MANUAL_SUBMODULES) - #check_submodule(external/trezor-common) - check_submodule(external/randomwow) +@@ -369,6 +369,8 @@ if(NOT MANUAL_SUBMODULES) + check_submodule(external/trezor-common) + check_submodule(external/randomx) check_submodule(external/supercop) + check_submodule(external/polyseed) + check_submodule(external/utf8proc) endif() endif() -@@ -459,7 +461,7 @@ endif() +@@ -458,7 +460,7 @@ endif() # elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSDI.*") # set(BSDI TRUE) @@ -137,13 +137,13 @@ index b016f2f48..f2f365b1b 100644 + } diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt -index 29aed0cc6..c023abffa 100644 +index 5b7f69a56..1b9761d70 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -70,3 +70,5 @@ add_subdirectory(db_drivers) add_subdirectory(easylogging++) add_subdirectory(qrcodegen) - add_subdirectory(randomwow EXCLUDE_FROM_ALL) + add_subdirectory(randomx EXCLUDE_FROM_ALL) +add_subdirectory(polyseed EXCLUDE_FROM_ALL) +add_subdirectory(utf8proc EXCLUDE_FROM_ALL) \ No newline at end of file @@ -156,13 +156,13 @@ index 000000000..b7c35bb3c +Subproject commit b7c35bb3c6b91e481ecb04fc235eaff69c507fa1 diff --git a/external/utf8proc b/external/utf8proc new file mode 160000 -index 000000000..1fe43f5a6 +index 000000000..1cb28a66c --- /dev/null +++ b/external/utf8proc @@ -0,0 +1 @@ -+Subproject commit 1fe43f5a6d9c628f717c5ec8aeaeae4a9adfd167 ++Subproject commit 1cb28a66ca79a0845e99433fd1056257456cef8b diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index 9216bcaa5..c043ba150 100644 +index 3335d3c21..06b708cf0 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -95,6 +95,7 @@ add_subdirectory(net) @@ -277,10 +277,10 @@ index 2ee9545d4..0099ebfe7 100644 const account_keys& get_keys() const; std::string get_public_address_str(network_type nettype) const; diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h -index 8c0d3ce20..1c1830ad4 100644 +index 61146a114..8e1a07110 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h -@@ -219,6 +219,8 @@ +@@ -207,6 +207,8 @@ #define DNS_BLOCKLIST_LIFETIME (86400 * 8) @@ -828,10 +828,10 @@ index 000000000..2c8c777a7 +#endif //POLYSEED_HPP \ No newline at end of file diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp -index d81ddec93..db9c2b5d9 100644 +index 8d7364cba..472f05016 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp -@@ -683,6 +683,28 @@ bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &p +@@ -690,6 +690,28 @@ bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &p return true; } @@ -860,7 +860,7 @@ index d81ddec93..db9c2b5d9 100644 Wallet::Device WalletImpl::getDeviceType() const { return static_cast(m_wallet->get_device_type()); -@@ -820,6 +842,55 @@ std::string WalletImpl::seed(const std::string& seed_offset) const +@@ -798,6 +820,55 @@ std::string WalletImpl::seed(const std::string& seed_offset) const return std::string(seed.data(), seed.size()); // TODO } @@ -875,7 +875,7 @@ index d81ddec93..db9c2b5d9 100644 + } + + bool result = m_wallet->get_polyseed(seed_words_epee, passphrase_epee); -+ ++ + seed_words.assign(seed_words_epee.data(), seed_words_epee.size()); + passphrase.assign(passphrase_epee.data(), passphrase_epee.size()); + @@ -897,7 +897,7 @@ index d81ddec93..db9c2b5d9 100644 +bool Wallet::createPolyseed(std::string &seed_words, std::string &err, const std::string &language) +{ + epee::wipeable_string seed_words_epee(seed_words.c_str(), seed_words.size()); -+ ++ + try { + polyseed::data polyseed(POLYSEED_COIN); + polyseed.create(0); @@ -917,10 +917,10 @@ index d81ddec93..db9c2b5d9 100644 { return m_wallet->get_seed_language(); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h -index 03b5a98e9..28135c82a 100644 +index ec2d7e9b3..787215ab3 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h -@@ -86,9 +86,19 @@ public: +@@ -79,9 +79,19 @@ public: bool recoverFromDevice(const std::string &path, const std::string &password, const std::string &device_name); @@ -941,10 +941,10 @@ index 03b5a98e9..28135c82a 100644 void setSeedLanguage(const std::string &arg) override; // void setListener(Listener *) {} diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h -index 6df661dc2..a0ed60a39 100644 +index 71991df0d..9ea753083 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h -@@ -800,6 +800,10 @@ struct Wallet +@@ -700,6 +700,10 @@ struct Wallet static void warning(const std::string &category, const std::string &str); static void error(const std::string &category, const std::string &str); @@ -955,7 +955,7 @@ index 6df661dc2..a0ed60a39 100644 /** * @brief StartRefresh - Start/resume refresh thread (refresh every 10 seconds) */ -@@ -1432,6 +1436,27 @@ struct WalletManager +@@ -1256,6 +1260,27 @@ struct WalletManager uint64_t kdf_rounds = 1, WalletListener * listener = nullptr) = 0; @@ -984,10 +984,10 @@ index 6df661dc2..a0ed60a39 100644 * \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted * \param wallet previously opened / created wallet instance diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp -index b166d8ac7..f88bd9e64 100644 +index e81b8f83a..c79fe25d6 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp -@@ -172,6 +172,15 @@ Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path, +@@ -156,6 +156,15 @@ Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path, return wallet; } @@ -1004,10 +1004,10 @@ index b166d8ac7..f88bd9e64 100644 { WalletImpl * wallet_ = dynamic_cast(wallet); diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h -index 206aedc14..e3149300c 100644 +index a223e1df9..28fcd36c9 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h -@@ -82,6 +82,16 @@ public: +@@ -75,6 +75,16 @@ public: const std::string &subaddressLookahead = "", uint64_t kdf_rounds = 1, WalletListener * listener = nullptr) override; @@ -1025,7 +1025,7 @@ index 206aedc14..e3149300c 100644 bool walletExists(const std::string &path) override; bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds = 1) const override; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp -index e586d67f7..83aba6253 100644 +index f34b10988..e4e02c782 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -92,6 +92,7 @@ using namespace epee; @@ -1036,17 +1036,17 @@ index e586d67f7..83aba6253 100644 extern "C" { -@@ -1272,7 +1273,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std +@@ -1260,7 +1261,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std m_enable_multisig(false), m_pool_info_query_time(0), m_has_ever_refreshed_from_node(false), -- m_allow_mismatched_daemon_version(true) -+ m_allow_mismatched_daemon_version(true), +- m_allow_mismatched_daemon_version(false) ++ m_allow_mismatched_daemon_version(false), + m_polyseed(false) { set_rpc_client_secret_key(rct::rct2sk(rct::skGen())); } -@@ -1450,10 +1452,25 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab +@@ -1438,10 +1440,25 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab key = cryptonote::encrypt_key(key, passphrase); if (!crypto::ElectrumWords::bytes_to_words(key, electrum_words, seed_language)) { @@ -1073,7 +1073,7 @@ index e586d67f7..83aba6253 100644 return true; } //---------------------------------------------------------------------------------------------------- -@@ -4712,6 +4729,9 @@ boost::optional wallet2::get_keys_file_data(const epee: +@@ -4629,6 +4646,9 @@ boost::optional wallet2::get_keys_file_data(const epee: value2.SetInt(m_enable_multisig ? 1 : 0); json.AddMember("enable_multisig", value2, json.GetAllocator()); @@ -1083,15 +1083,15 @@ index e586d67f7..83aba6253 100644 // Serialize the JSON object rapidjson::StringBuffer buffer; rapidjson::Writer writer(buffer); -@@ -4860,6 +4880,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st +@@ -4776,6 +4796,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_credits_target = 0; m_enable_multisig = false; - m_allow_mismatched_daemon_version = true; + m_allow_mismatched_daemon_version = false; + m_polyseed = false; } else if(json.IsObject()) { -@@ -5098,6 +5119,8 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st +@@ -5012,6 +5033,8 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_credits_target = field_credits_target; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, enable_multisig, int, Int, false, false); m_enable_multisig = field_enable_multisig; @@ -1100,7 +1100,7 @@ index e586d67f7..83aba6253 100644 } else { -@@ -5370,6 +5393,48 @@ void wallet2::init_type(hw::device::device_type device_type) +@@ -5284,6 +5307,48 @@ void wallet2::init_type(hw::device::device_type device_type) m_key_device_type = device_type; } @@ -1149,7 +1149,7 @@ index e586d67f7..83aba6253 100644 /*! * \brief Generates a wallet or restores one. Assumes the multisig setup * has already completed for the provided multisig info. -@@ -5497,7 +5562,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip +@@ -5411,7 +5476,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip return retval; } @@ -1158,7 +1158,7 @@ index e586d67f7..83aba6253 100644 { // -1 month for fluctuations in block time and machine date/time setup. // avg seconds per block -@@ -5521,7 +5586,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip +@@ -5435,7 +5500,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip // the daemon is currently syncing. // If we use the approximate height we subtract one month as // a safety margin. @@ -1167,59 +1167,66 @@ index e586d67f7..83aba6253 100644 uint64_t target_height = get_daemon_blockchain_target_height(err); if (err.empty()) { if (target_height < height) -@@ -13546,9 +13611,9 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err) +@@ -13135,7 +13200,7 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err) return target_height; } -uint64_t wallet2::get_approximate_blockchain_height() const +uint64_t wallet2::get_approximate_blockchain_height(uint64_t t) const { -- uint64_t approx_blockchain_height = m_nettype == TESTNET ? 0 : (time(NULL) - 1522624244)/307; -+ uint64_t approx_blockchain_height = m_nettype == TESTNET ? 0 : ((t > 0 ? t : time(NULL)) - 1522624244)/307; - LOG_PRINT_L2("Calculated blockchain height: " << approx_blockchain_height); - return approx_blockchain_height; - } -@@ -15262,6 +15327,21 @@ bool wallet2::parse_uri(const std::string &uri, std::string &address, std::strin + // time of v2 fork + const time_t fork_time = m_nettype == TESTNET ? 1448285909 : m_nettype == STAGENET ? 1520937818 : 1458748658; +@@ -13144,7 +13209,7 @@ uint64_t wallet2::get_approximate_blockchain_height() const + // avg seconds per block + const int seconds_per_block = DIFFICULTY_TARGET_V2; + // Calculated blockchain height +- uint64_t approx_blockchain_height = fork_block + (time(NULL) - fork_time)/seconds_per_block; ++ uint64_t approx_blockchain_height = fork_block + ((t > 0 ? t : time(NULL)) - fork_time)/seconds_per_block; + // testnet and stagenet got some huge rollbacks, so the estimation is way off + static const uint64_t approximate_rolled_back_blocks = m_nettype == TESTNET ? 342100 : 30000; + if ((m_nettype == TESTNET || m_nettype == STAGENET) && approx_blockchain_height > approximate_rolled_back_blocks) +@@ -14862,15 +14927,6 @@ bool wallet2::parse_uri(const std::string &uri, std::string &address, std::strin //---------------------------------------------------------------------------------------------------- uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, uint8_t day) { -+ std::tm date = { 0, 0, 0, 0, 0, 0, 0, 0 }; -+ date.tm_year = year - 1900; -+ date.tm_mon = month - 1; -+ date.tm_mday = day; -+ if (date.tm_mon < 0 || 11 < date.tm_mon || date.tm_mday < 1 || 31 < date.tm_mday) -+ { -+ throw std::runtime_error("month or day out of range"); -+ } +- uint32_t version; +- if (!check_connection(&version)) +- { +- throw std::runtime_error("failed to connect to daemon: " + get_daemon_address()); +- } +- if (version < MAKE_CORE_RPC_VERSION(1, 6)) +- { +- throw std::runtime_error("this function requires RPC version 1.6 or higher"); +- } + std::tm date = { 0, 0, 0, 0, 0, 0, 0, 0 }; + date.tm_year = year - 1900; + date.tm_mon = month - 1; +@@ -14879,7 +14935,23 @@ uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, ui + { + throw std::runtime_error("month or day out of range"); + } + -+ uint64_t timestamp_target = std::mktime(&date); + uint64_t timestamp_target = std::mktime(&date); + + return get_blockchain_height_by_timestamp(timestamp_target); +} + +uint64_t wallet2::get_blockchain_height_by_timestamp(uint64_t timestamp_target) { - uint32_t version; - if (!check_connection(&version)) - { -@@ -15271,15 +15351,7 @@ uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, ui - { - throw std::runtime_error("this function requires RPC version 1.6 or higher"); - } -- std::tm date = { 0, 0, 0, 0, 0, 0, 0, 0 }; -- date.tm_year = year - 1900; -- date.tm_mon = month - 1; -- date.tm_mday = day; -- if (date.tm_mon < 0 || 11 < date.tm_mon || date.tm_mday < 1 || 31 < date.tm_mday) -- { -- throw std::runtime_error("month or day out of range"); -- } -- uint64_t timestamp_target = std::mktime(&date); ++ uint32_t version; ++ if (!check_connection(&version)) ++ { ++ throw std::runtime_error("failed to connect to daemon: " + get_daemon_address()); ++ } ++ if (version < MAKE_CORE_RPC_VERSION(1, 6)) ++ { ++ throw std::runtime_error("this function requires RPC version 1.6 or higher"); ++ } + std::string err; uint64_t height_min = 0; uint64_t height_max = get_daemon_blockchain_height(err) - 1; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h -index df34f9abf..db5c1feb3 100644 +index 3144a8fd3..b540eff6b 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -72,6 +72,7 @@ @@ -1267,7 +1274,7 @@ index df34f9abf..db5c1feb3 100644 /*! * \brief Checks if light wallet. A light wallet sends view key to a server where the blockchain is scanned. */ -@@ -1469,8 +1493,8 @@ private: +@@ -1466,8 +1490,8 @@ private: /*! * \brief Calculates the approximate blockchain height from current date/time. */ @@ -1278,7 +1285,7 @@ index df34f9abf..db5c1feb3 100644 std::vector select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool allow_rct); std::vector select_available_outputs(const std::function &f); std::vector select_available_unmixable_outputs(); -@@ -1563,6 +1587,7 @@ private: +@@ -1559,6 +1583,7 @@ private: 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 &unknown_parameters, std::string &error); uint64_t get_blockchain_height_by_date(uint16_t year, uint8_t month, uint8_t day); // 1<=month<=12, 1<=day<=31 @@ -1286,7 +1293,7 @@ index df34f9abf..db5c1feb3 100644 bool is_synced(); -@@ -1900,6 +1925,7 @@ private: +@@ -1874,6 +1899,7 @@ private: std::string seed_language; /*!< Language of the mnemonics (seed). */ bool is_old_file_format; /*!< Whether the wallet file is of an old file format */ bool m_watch_only; /*!< no spend key */ @@ -1294,3 +1301,6 @@ index df34f9abf..db5c1feb3 100644 bool m_multisig; /*!< if > 1 spend secret key will not match spend public key */ uint32_t m_multisig_threshold; std::vector m_multisig_signers; +-- +2.44.0 + diff --git a/patches/monero/0001-background-sync.patch b/patches/monero/0002-wallet-background-sync-with-just-the-view-key.patch similarity index 92% rename from patches/monero/0001-background-sync.patch rename to patches/monero/0002-wallet-background-sync-with-just-the-view-key.patch index 63e95cb..610e5bd 100644 --- a/patches/monero/0001-background-sync.patch +++ b/patches/monero/0002-wallet-background-sync-with-just-the-view-key.patch @@ -1,30 +1,53 @@ -From c7da75fee9bea42a6a741905cf6212db5ea8c54b Mon Sep 17 00:00:00 2001 -From: Czarek Nakamoto -Date: Tue, 12 Mar 2024 10:02:23 +0100 -Subject: [PATCH] PATCH: background-sync +From 0cc1775c6a41a1768ebbe6155496f01289f903d4 Mon Sep 17 00:00:00 2001 +From: j-berman +Date: Thu, 13 Oct 2022 18:33:33 -0700 +Subject: [PATCH 2/8] wallet: background sync with just the view key +- When background syncing, the wallet wipes the spend key +from memory and processes all new transactions. The wallet saves +all receives, spends, and "plausible" spends of receives the +wallet does not know key images for. +- When background sync disabled, the wallet processes all +background synced txs and then clears the background sync cache. +- Adding "plausible" spends to the background sync cache ensures +that the wallet does not need to query the daemon to see if any +received outputs were spent while background sync was enabled. +This would harm privacy especially for users of 3rd party daemons. +- To enable the feature in the CLI wallet, the user can set +background-sync to reuse-wallet-password or +custom-background-password and the wallet automatically syncs in +the background when the wallet locks, then processes all +background synced txs when the wallet is unlocked. +- The custom-background-password option enables the user to +open a distinct background wallet that only has a view key saved +and can be opened/closed/synced separately from the main wallet. +When the main wallet opens, it processes the background wallet's +cache. +- To enable the feature in the RPC wallet, there is a new +`/setup_background_sync` endpoint. +- HW, multsig and view-only wallets cannot background sync. --- - src/cryptonote_basic/account.cpp | 11 + - src/cryptonote_basic/account.h | 1 + - src/cryptonote_config.h | 3 + - src/simplewallet/simplewallet.cpp | 205 +++- - src/simplewallet/simplewallet.h | 1 + - src/wallet/api/wallet.cpp | 213 ++++- - src/wallet/api/wallet.h | 12 + - src/wallet/api/wallet2_api.h | 42 + - src/wallet/wallet2.cpp | 948 ++++++++++++++++++- - src/wallet/wallet2.h | 142 ++- - src/wallet/wallet_errors.h | 39 + - src/wallet/wallet_rpc_server.cpp | 162 ++++ - src/wallet/wallet_rpc_server.h | 6 + - src/wallet/wallet_rpc_server_commands_defs.h | 64 ++ - src/wallet/wallet_rpc_server_error_codes.h | 2 + - tests/functional_tests/transfer.py | 401 +++++++- - tests/functional_tests/util_resources.py | 25 + - tests/functional_tests/wallet.py | 43 +- - tests/unit_tests/wipeable_string.cpp | 12 + - utils/python-rpc/framework/wallet.py | 35 + - 20 files changed, 2281 insertions(+), 86 deletions(-) + src/cryptonote_basic/account.cpp | 11 + + src/cryptonote_basic/account.h | 1 + + src/cryptonote_config.h | 2 + + src/simplewallet/simplewallet.cpp | 205 +++- + src/simplewallet/simplewallet.h | 1 + + src/wallet/api/wallet.cpp | 213 +++- + src/wallet/api/wallet.h | 12 + + src/wallet/api/wallet2_api.h | 42 + + src/wallet/wallet2.cpp | 1029 ++++++++++++++++-- + src/wallet/wallet2.h | 156 ++- + src/wallet/wallet_errors.h | 39 + + src/wallet/wallet_rpc_server.cpp | 162 +++ + src/wallet/wallet_rpc_server.h | 6 + + src/wallet/wallet_rpc_server_commands_defs.h | 64 ++ + src/wallet/wallet_rpc_server_error_codes.h | 2 + + tests/functional_tests/transfer.py | 400 ++++++- + tests/functional_tests/util_resources.py | 25 + + tests/functional_tests/wallet.py | 43 +- + tests/unit_tests/wipeable_string.cpp | 12 + + utils/python-rpc/framework/wallet.py | 42 + + 20 files changed, 2337 insertions(+), 130 deletions(-) diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp index 4931c3740..2d556f285 100644 @@ -61,18 +84,10 @@ index 0099ebfe7..1f76febce 100644 void encrypt_keys(const crypto::chacha_key &key) { m_keys.encrypt(key); } diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h -index 8e1a07110..cf50b2adc 100644 +index 8e1a07110..3af3a63a1 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h -@@ -233,6 +233,7 @@ namespace config - } }; // Bender's nightmare - std::string const GENESIS_TX = "013c01ff0001ffffffffffff03029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121017767aafcde9be00dcfd098715ebcf7f410daebc582fda69d24a28e9d0bc890d1"; - uint32_t const GENESIS_NONCE = 10000; -+ std::string const BACKGROUND_WALLET_SUFFIX = ".background"; - - // Hash domain separators - const char HASH_KEY_BULLETPROOF_EXPONENT[] = "bulletproof"; -@@ -243,6 +244,8 @@ namespace config +@@ -243,6 +243,8 @@ namespace config const unsigned char HASH_KEY_ENCRYPTED_PAYMENT_ID = 0x8d; const unsigned char HASH_KEY_WALLET = 0x8c; const unsigned char HASH_KEY_WALLET_CACHE = 0x8d; @@ -1295,10 +1310,19 @@ index 9ea753083..4268b656e 100644 virtual AddressBook * addressBook() = 0; virtual Subaddress * subaddress() = 0; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp -index e4e02c782..618c43cee 100644 +index e4e02c782..c7cbdbbe6 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp -@@ -1010,14 +1010,14 @@ uint64_t num_priv_multisig_keys_post_setup(uint64_t threshold, uint64_t total) +@@ -158,6 +158,8 @@ static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1"; + + static const std::string ASCII_OUTPUT_MAGIC = "MoneroAsciiDataV1"; + ++static const std::string BACKGROUND_WALLET_SUFFIX = ".background"; ++ + boost::mutex tools::wallet2::default_daemon_address_lock; + std::string tools::wallet2::default_daemon_address = ""; + +@@ -1010,14 +1012,14 @@ uint64_t num_priv_multisig_keys_post_setup(uint64_t threshold, uint64_t total) * @param keys_data_key the chacha key that encrypts wallet keys files * @return crypto::chacha_key the chacha key that encrypts the wallet cache files */ @@ -1315,7 +1339,7 @@ index e4e02c782..618c43cee 100644 cn_fast_hash(cache_key_data.data(), HASH_SIZE+1, (crypto::hash&) cache_key); return cache_key; -@@ -1105,7 +1105,7 @@ wallet_keys_unlocker::wallet_keys_unlocker(wallet2 &w, const boost::optional lock(lockers_lock); if (lockers++ > 0) locked = false; @@ -1324,7 +1348,7 @@ index e4e02c782..618c43cee 100644 { locked = false; return; -@@ -1222,6 +1222,11 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std +@@ -1222,6 +1224,11 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std m_ignore_outputs_above(MONEY_SUPPLY), m_ignore_outputs_below(0), m_track_uses(false), @@ -1336,7 +1360,7 @@ index e4e02c782..618c43cee 100644 m_show_wallet_name_when_locked(false), m_inactivity_lock_timeout(DEFAULT_INACTIVITY_LOCK_TIMEOUT), m_setup_background_mining(BackgroundMiningMaybe), -@@ -1877,6 +1882,9 @@ bool has_nonrequested_tx_at_height_or_above_requested(uint64_t height, const std +@@ -1877,6 +1884,9 @@ bool has_nonrequested_tx_at_height_or_above_requested(uint64_t height, const std //---------------------------------------------------------------------------------------------------- void wallet2::scan_tx(const std::unordered_set &txids) { @@ -1346,7 +1370,7 @@ index e4e02c782..618c43cee 100644 // Get the transactions from daemon in batches sorted lowest height to highest tx_entry_data txs_to_scan = get_tx_entries(txids); if (txs_to_scan.tx_entries.empty()) -@@ -2184,11 +2192,11 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons +@@ -2184,11 +2194,11 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons THROW_WALLET_EXCEPTION_IF(i >= tx.vout.size(), error::wallet_internal_error, "Invalid vout index"); // if keys are encrypted, ask for password @@ -1360,7 +1384,7 @@ index e4e02c782..618c43cee 100644 { boost::optional pwd = m_callback->on_get_password(pool ? "output found in pool" : "output received"); THROW_WALLET_EXCEPTION_IF(!pwd, error::password_needed, tr("Password is needed to compute key image for incoming monero")); -@@ -2200,7 +2208,7 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons +@@ -2200,7 +2210,7 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons crypto::public_key output_public_key; THROW_WALLET_EXCEPTION_IF(!get_output_public_key(tx.vout[i], output_public_key), error::wallet_internal_error, "Failed to get output public key"); @@ -1369,7 +1393,7 @@ index e4e02c782..618c43cee 100644 { tx_scan_info.in_ephemeral.pub = output_public_key; tx_scan_info.in_ephemeral.sec = crypto::null_skey; -@@ -2457,6 +2465,14 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote +@@ -2457,6 +2467,22 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote THROW_WALLET_EXCEPTION_IF(tx.vout.size() != o_indices.size(), error::wallet_internal_error, "transactions outputs size=" + std::to_string(tx.vout.size()) + " not match with daemon response size=" + std::to_string(o_indices.size())); @@ -1378,13 +1402,21 @@ index e4e02c782..618c43cee 100644 + if (m_background_syncing && m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end()) + { + size_t bgs_idx = m_background_sync_data.txs.size(); ++ background_synced_tx_t bgs_tx = { ++ .index_in_background_sync_data = bgs_idx, ++ .tx = tx, ++ .output_indices = o_indices, ++ .height = height, ++ .block_timestamp = ts, ++ .double_spend_seen = double_spend_seen ++ }; + LOG_PRINT_L2("Adding received tx " << txid << " to background sync data (idx=" << bgs_idx << ")"); -+ m_background_sync_data.txs.insert({txid, background_synced_tx{bgs_idx, tx, o_indices, height, ts, double_spend_seen}}); ++ m_background_sync_data.txs.insert({txid, std::move(bgs_tx)}); + } } for(size_t o: outs) -@@ -2482,7 +2498,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote +@@ -2482,7 +2508,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote td.m_tx = (const cryptonote::transaction_prefix&)tx; td.m_txid = txid; td.m_key_image = tx_scan_info[o].ki; @@ -1393,7 +1425,7 @@ index e4e02c782..618c43cee 100644 if (!td.m_key_image_known) { // we might have cold signed, and have a mapping to key images -@@ -2672,10 +2688,17 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote +@@ -2672,10 +2698,25 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote set_spent(it->second, height); if (!ignore_callbacks && 0 != m_callback) m_callback->on_money_spent(height, txid, tx, amount, tx, td.m_subaddr_index); @@ -1401,8 +1433,16 @@ index e4e02c782..618c43cee 100644 + if (m_background_syncing && m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end()) + { + size_t bgs_idx = m_background_sync_data.txs.size(); ++ background_synced_tx_t bgs_tx = { ++ .index_in_background_sync_data = bgs_idx, ++ .tx = tx, ++ .output_indices = o_indices, ++ .height = height, ++ .block_timestamp = ts, ++ .double_spend_seen = double_spend_seen ++ }; + LOG_PRINT_L2("Adding spent tx " << txid << " to background sync data (idx=" << bgs_idx << ")"); -+ m_background_sync_data.txs.insert({txid, background_synced_tx{bgs_idx, tx, o_indices, height, ts, double_spend_seen}}); ++ m_background_sync_data.txs.insert({txid, std::move(bgs_tx)}); + } } } @@ -1412,7 +1452,7 @@ index e4e02c782..618c43cee 100644 { PERF_TIMER(track_uses); const uint64_t amount = in_to_key.amount; -@@ -2689,7 +2712,19 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote +@@ -2689,7 +2730,27 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote { size_t idx = i->second; THROW_WALLET_EXCEPTION_IF(idx >= m_transfers.size(), error::wallet_internal_error, "Output tracker cache index out of range"); @@ -1427,13 +1467,21 @@ index e4e02c782..618c43cee 100644 + if (m_background_syncing && !m_transfers[idx].m_key_image_known && m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end()) + { + size_t bgs_idx = m_background_sync_data.txs.size(); ++ background_synced_tx_t bgs_tx = { ++ .index_in_background_sync_data = bgs_idx, ++ .tx = tx, ++ .output_indices = o_indices, ++ .height = height, ++ .block_timestamp = ts, ++ .double_spend_seen = double_spend_seen ++ }; + LOG_PRINT_L2("Adding plausible spent tx " << txid << " to background sync data (idx=" << bgs_idx << ")"); -+ m_background_sync_data.txs.insert({txid, background_synced_tx{bgs_idx, tx, o_indices, height, ts, double_spend_seen}}); ++ m_background_sync_data.txs.insert({txid, std::move(bgs_tx)}); + } } } } -@@ -2699,7 +2734,16 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote +@@ -2699,7 +2760,24 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote continue; for (uint64_t offset: offsets) if (offset == td.m_global_output_index) @@ -1444,14 +1492,22 @@ index e4e02c782..618c43cee 100644 + if (m_background_syncing && !td.m_key_image_known && m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end()) + { + size_t bgs_idx = m_background_sync_data.txs.size(); ++ background_synced_tx_t bgs_tx = { ++ .index_in_background_sync_data = bgs_idx, ++ .tx = tx, ++ .output_indices = o_indices, ++ .height = height, ++ .block_timestamp = ts, ++ .double_spend_seen = double_spend_seen ++ }; + LOG_PRINT_L2("Adding plausible spent tx " << txid << " to background sync data (idx=" << bgs_idx << ")"); -+ m_background_sync_data.txs.insert({txid, background_synced_tx{bgs_idx, tx, o_indices, height, ts, double_spend_seen}}); ++ m_background_sync_data.txs.insert({txid, std::move(bgs_tx)}); + } + } } } } -@@ -3072,8 +3116,8 @@ void wallet2::pull_blocks(bool first, bool try_incremental, uint64_t start_heigh +@@ -3072,8 +3150,8 @@ void wallet2::pull_blocks(bool first, bool try_incremental, uint64_t start_heigh req.start_height = start_height; req.no_miner_tx = m_refresh_type == RefreshNoCoinbase; @@ -1462,7 +1518,7 @@ index e4e02c782..618c43cee 100644 req.pool_info_since = m_pool_info_query_time; { -@@ -3100,7 +3144,7 @@ void wallet2::pull_blocks(bool first, bool try_incremental, uint64_t start_heigh +@@ -3100,7 +3178,7 @@ void wallet2::pull_blocks(bool first, bool try_incremental, uint64_t start_heigh << ", height " << blocks_start_height + blocks.size() << ", node height " << res.current_height << ", pool info " << static_cast(res.pool_info_extent)); @@ -1471,7 +1527,7 @@ index e4e02c782..618c43cee 100644 { if (res.pool_info_extent != COMMAND_RPC_GET_BLOCKS_FAST::NONE) { -@@ -3612,6 +3656,9 @@ void wallet2::process_unconfirmed_transfer(bool incremental, const crypto::hash +@@ -3612,6 +3690,9 @@ void wallet2::process_unconfirmed_transfer(bool incremental, const crypto::hash // incremental update anymore, because with that we might miss some txs altogether. void wallet2::update_pool_state(std::vector> &process_txs, bool refreshed, bool try_incremental) { @@ -1481,7 +1537,7 @@ index e4e02c782..618c43cee 100644 bool updated = false; if (m_pool_info_query_time != 0 && try_incremental) { -@@ -4182,6 +4229,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo +@@ -4182,6 +4263,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo } m_first_refresh_done = true; @@ -1490,7 +1546,7 @@ index e4e02c782..618c43cee 100644 LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", balance (all accounts): " << print_money(balance_all(false)) << ", unlocked: " << print_money(unlocked_balance_all(false))); } -@@ -4267,6 +4316,14 @@ wallet2::detached_blockchain_data wallet2::detach_blockchain(uint64_t height, st +@@ -4267,6 +4350,14 @@ wallet2::detached_blockchain_data wallet2::detach_blockchain(uint64_t height, st td.m_uses.pop_back(); } @@ -1505,8 +1561,11 @@ index e4e02c782..618c43cee 100644 if (output_tracker_cache) output_tracker_cache->clear(); -@@ -4343,6 +4400,9 @@ void wallet2::handle_reorg(uint64_t height, std::map m_blockchain.offset(), error::wallet_internal_error, "Daemon claims reorg below last checkpoint"); ++ detached_blockchain_data dbd = detach_blockchain(height, output_tracker_cache); + if (m_background_syncing && height < m_background_sync_data.start_height) @@ -1515,7 +1574,7 @@ index e4e02c782..618c43cee 100644 if (m_callback) m_callback->on_reorg(height, dbd.detached_blockchain.size(), dbd.detached_tx_hashes.size()); } -@@ -4352,6 +4412,7 @@ bool wallet2::deinit() +@@ -4352,6 +4447,7 @@ bool wallet2::deinit() if(m_is_initialized) { m_is_initialized = false; unlock_keys_file(); @@ -1523,23 +1582,19 @@ index e4e02c782..618c43cee 100644 m_account.deinit(); } return true; -@@ -4378,6 +4439,9 @@ bool wallet2::clear() +@@ -4378,6 +4474,7 @@ bool wallet2::clear() m_device_last_key_image_sync = 0; m_pool_info_query_time = 0; m_skip_to_height = 0; -+ m_background_sync_data.first_refresh_done = false; -+ m_background_sync_data.start_height = 0; -+ m_background_sync_data.txs.clear(); ++ m_background_sync_data = background_sync_data_t{}; return true; } //---------------------------------------------------------------------------------------------------- -@@ -4396,13 +4460,32 @@ void wallet2::clear_soft(bool keep_key_images) +@@ -4396,13 +4493,30 @@ void wallet2::clear_soft(bool keep_key_images) m_scanned_pool_txs[1].clear(); m_pool_info_query_time = 0; m_skip_to_height = 0; -+ m_background_sync_data.first_refresh_done = false; -+ m_background_sync_data.start_height = 0; -+ m_background_sync_data.txs.clear(); ++ m_background_sync_data = background_sync_data_t{}; cryptonote::block b; generate_genesis(b); @@ -1567,7 +1622,7 @@ index e4e02c782..618c43cee 100644 /*! * \brief Stores wallet information to wallet file. * \param keys_file_name Name of wallet file -@@ -4414,16 +4497,35 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable +@@ -4414,16 +4528,35 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable { boost::optional keys_file_data = get_keys_file_data(password, watch_only); CHECK_AND_ASSERT_MES(keys_file_data != boost::none, false, "failed to generate wallet keys data"); @@ -1607,7 +1662,7 @@ index e4e02c782..618c43cee 100644 if (e) { boost::filesystem::remove(tmp_file_name); -@@ -4435,26 +4537,27 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable +@@ -4435,26 +4568,27 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable } //---------------------------------------------------------------------------------------------------- boost::optional wallet2::get_keys_file_data(const epee::wipeable_string& password, bool watch_only) @@ -1643,7 +1698,7 @@ index e4e02c782..618c43cee 100644 account.forget_spend_key(); account.encrypt_keys(key); -@@ -4589,6 +4692,9 @@ boost::optional wallet2::get_keys_file_data(const epee: +@@ -4589,6 +4723,9 @@ boost::optional wallet2::get_keys_file_data(const epee: value2.SetInt(m_track_uses ? 1 : 0); json.AddMember("track_uses", value2, json.GetAllocator()); @@ -1653,21 +1708,19 @@ index e4e02c782..618c43cee 100644 value2.SetInt(m_show_wallet_name_when_locked ? 1 : 0); json.AddMember("show_wallet_name_when_locked", value2, json.GetAllocator()); -@@ -4646,6 +4752,13 @@ boost::optional wallet2::get_keys_file_data(const epee: - value2.SetInt(m_enable_multisig ? 1 : 0); - json.AddMember("enable_multisig", value2, json.GetAllocator()); +@@ -4648,6 +4785,11 @@ boost::optional wallet2::get_keys_file_data(const epee: + value2.SetInt(m_polyseed ? 1 : 0); + json.AddMember("polyseed", value2, json.GetAllocator()); + if (m_background_sync_type == BackgroundSyncCustomPassword && !background_keys_file && m_custom_background_key) + { + value.SetString(reinterpret_cast(m_custom_background_key.get().data()), m_custom_background_key.get().size()); + json.AddMember("custom_background_key", value, json.GetAllocator()); + } -+ -+ - value2.SetInt(m_polyseed ? 1 : 0); - json.AddMember("polyseed", value2, json.GetAllocator()); -@@ -4675,13 +4788,81 @@ void wallet2::setup_keys(const epee::wipeable_string &password) + // Serialize the JSON object + rapidjson::StringBuffer buffer; +@@ -4675,13 +4817,81 @@ void wallet2::setup_keys(const epee::wipeable_string &password) m_account.decrypt_viewkey(key); } @@ -1750,7 +1803,7 @@ index e4e02c782..618c43cee 100644 if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only) decrypt_keys(original_password); setup_keys(new_password); -@@ -4740,8 +4921,24 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st +@@ -4740,8 +4950,24 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st std::string account_data; account_data.resize(keys_file_data.account_data.size()); crypto::chacha20(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); @@ -1776,7 +1829,7 @@ index e4e02c782..618c43cee 100644 // The contents should be JSON if the wallet follows the new format. if (json.Parse(account_data.c_str()).HasParseError()) { -@@ -4779,6 +4976,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st +@@ -4779,6 +5005,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_ignore_outputs_above = MONEY_SUPPLY; m_ignore_outputs_below = 0; m_track_uses = false; @@ -1784,18 +1837,18 @@ index e4e02c782..618c43cee 100644 m_show_wallet_name_when_locked = false; m_inactivity_lock_timeout = DEFAULT_INACTIVITY_LOCK_TIMEOUT; m_setup_background_mining = BackgroundMiningMaybe; -@@ -4796,6 +4994,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st - m_credits_target = 0; +@@ -4797,6 +5024,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_enable_multisig = false; m_allow_mismatched_daemon_version = false; -+ m_custom_background_key = boost::none; m_polyseed = false; ++ m_custom_background_key = boost::none; } else if(json.IsObject()) -@@ -5034,6 +5233,40 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, enable_multisig, int, Int, false, false); + { +@@ -5035,6 +5263,39 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_enable_multisig = field_enable_multisig; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, polyseed, int, Int, false, false); + m_polyseed = field_polyseed; + + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, background_sync_type, BackgroundSyncType, Int, false, BackgroundSyncOff); + m_background_sync_type = field_background_sync_type; @@ -1829,11 +1882,10 @@ index e4e02c782..618c43cee 100644 + { + LOG_ERROR("Unexpected field custom_background_key found in JSON"); + } -+ - m_polyseed = field_polyseed; } else -@@ -5098,12 +5331,17 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st + { +@@ -5098,12 +5359,17 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st const cryptonote::account_keys& keys = m_account.get_keys(); hw::device &hwdev = m_account.get_device(); r = r && hwdev.verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key); @@ -1853,7 +1905,7 @@ index e4e02c782..618c43cee 100644 return true; } -@@ -5118,11 +5356,12 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st +@@ -5118,11 +5384,12 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st * can be used prior to rewriting wallet keys file, to ensure user has entered the correct password * */ @@ -1868,7 +1920,7 @@ index e4e02c782..618c43cee 100644 lock_keys_file(); return r; } -@@ -5140,7 +5379,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password) +@@ -5140,7 +5407,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password) * can be used prior to rewriting wallet keys file, to ensure user has entered the correct password * */ @@ -1877,7 +1929,7 @@ index e4e02c782..618c43cee 100644 { rapidjson::Document json; wallet2::keys_file_data keys_file_data; -@@ -5157,9 +5396,22 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip +@@ -5157,9 +5424,22 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip std::string account_data; account_data.resize(keys_file_data.account_data.size()); crypto::chacha20(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); @@ -1901,7 +1953,7 @@ index e4e02c782..618c43cee 100644 // The contents should be JSON if the wallet follows the new format. if (json.Parse(account_data.c_str()).HasParseError()) { -@@ -5184,6 +5436,7 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip +@@ -5184,6 +5464,7 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip r = r && hwdev.verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key); if(!no_spend_key) r = r && hwdev.verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spend_public_key); @@ -1909,7 +1961,7 @@ index e4e02c782..618c43cee 100644 return r; } -@@ -5195,9 +5448,7 @@ void wallet2::encrypt_keys(const crypto::chacha_key &key) +@@ -5195,9 +5476,7 @@ void wallet2::encrypt_keys(const crypto::chacha_key &key) void wallet2::decrypt_keys(const crypto::chacha_key &key) { @@ -1920,7 +1972,7 @@ index e4e02c782..618c43cee 100644 m_account.encrypt_viewkey(key); m_account.decrypt_keys(key); -@@ -5915,11 +6166,30 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin +@@ -5915,11 +6194,30 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin { if (wallet_name.empty()) return; @@ -1951,13 +2003,13 @@ index e4e02c782..618c43cee 100644 } /*! * \brief Writes to a file named based on the normal wallet (doesn't generate key, assumes it's already there) -@@ -5953,6 +6223,16 @@ bool wallet2::wallet_valid_path_format(const std::string& file_path) +@@ -5953,6 +6251,16 @@ bool wallet2::wallet_valid_path_format(const std::string& file_path) return !file_path.empty(); } //---------------------------------------------------------------------------------------------------- +std::string wallet2::make_background_wallet_file_name(const std::string &wallet_file) +{ -+ return wallet_file + config::BACKGROUND_WALLET_SUFFIX; ++ return wallet_file + BACKGROUND_WALLET_SUFFIX; +} +//---------------------------------------------------------------------------------------------------- +std::string wallet2::make_background_keys_file_name(const std::string &wallet_file) @@ -1968,7 +2020,7 @@ index e4e02c782..618c43cee 100644 bool wallet2::parse_long_payment_id(const std::string& payment_id_str, crypto::hash& payment_id) { cryptonote::blobdata payment_id_data; -@@ -6188,10 +6468,135 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass +@@ -6188,10 +6496,81 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass THROW_WALLET_EXCEPTION_IF(true, error::file_read_error, "failed to load keys from buffer"); } @@ -1982,6 +2034,20 @@ index e4e02c782..618c43cee 100644 + if (!m_persistent_rpc_client_id) + set_rpc_client_secret_key(rct::rct2sk(rct::skGen())); + ++ // Wallets used to wipe, but not erase, old unused multisig key info, which lead to huge memory leaks. ++ // Here we erase these multisig keys if they're zero'd out to free up space. ++ for (auto &td : m_transfers) ++ { ++ auto mk_it = td.m_multisig_k.begin(); ++ while (mk_it != td.m_multisig_k.end()) ++ { ++ if (*mk_it == rct::zero()) ++ mk_it = td.m_multisig_k.erase(mk_it); ++ else ++ ++mk_it; ++ } ++ } ++ + cryptonote::block genesis; + generate_genesis(genesis); + crypto::hash genesis_hash = get_block_hash(genesis); @@ -2031,6 +2097,36 @@ index e4e02c782..618c43cee 100644 + } +} +//---------------------------------------------------------------------------------------------------- ++void wallet2::load_wallet_cache(const bool use_fs, const std::string& cache_buf) ++{ ++ boost::system::error_code e; + bool cache_missing = use_fs ? (!boost::filesystem::exists(m_wallet_file, e) || e) : cache_buf.empty(); + if (cache_missing) + { +@@ -6205,7 +6584,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass + bool r = true; + if (use_fs) + { +- load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits::max()); ++ r = load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits::max()); + THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, m_wallet_file); + } + +@@ -6218,7 +6597,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass + THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "internal error: failed to deserialize \"" + m_wallet_file + '\"'); + std::string cache_data; + cache_data.resize(cache_file_data.cache_data.size()); +- crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), m_cache_key, cache_file_data.iv, &cache_data[0]); ++ crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), get_cache_key(), cache_file_data.iv, &cache_data[0]); + + try { + bool loaded = false; +@@ -6308,60 +6687,76 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass + m_account_public_address.m_view_public_key != m_account.get_keys().m_account_address.m_view_public_key, + error::wallet_files_doesnt_correspond, m_keys_file, m_wallet_file); + } ++} ++//---------------------------------------------------------------------------------------------------- +void wallet2::process_background_cache_on_open() +{ + if (m_wallet_file.empty()) @@ -2039,17 +2135,25 @@ index e4e02c782..618c43cee 100644 + return; + if (m_background_sync_type == BackgroundSyncOff) + return; + +- if (!m_persistent_rpc_client_id) +- set_rpc_client_secret_key(rct::rct2sk(rct::skGen())); + if (m_background_sync_type == BackgroundSyncReusePassword) + { + const background_sync_data_t background_sync_data = m_background_sync_data; + const hashchain blockchain = m_blockchain; + process_background_cache(background_sync_data, blockchain, m_last_block_reward); -+ + +- // Wallets used to wipe, but not erase, old unused multisig key info, which lead to huge memory leaks. +- // Here we erase these multisig keys if they're zero'd out to free up space. +- for (auto &td : m_transfers) + // Reset the background cache after processing + reset_background_sync_data(m_background_sync_data); + } + else if (m_background_sync_type == BackgroundSyncCustomPassword) -+ { + { +- auto mk_it = td.m_multisig_k.begin(); +- while (mk_it != td.m_multisig_k.end()) + // If the background wallet files don't exist, recreate them + const std::string background_keys_file = make_background_keys_file_name(m_wallet_file); + const std::string background_wallet_file = make_background_wallet_file_name(m_wallet_file); @@ -2060,31 +2164,64 @@ index e4e02c782..618c43cee 100644 + THROW_WALLET_EXCEPTION_IF(!m_custom_background_key, error::wallet_internal_error, "Custom background key not set"); + + if (!background_keys_file_exists) -+ { + { +- if (*mk_it == rct::zero()) +- mk_it = td.m_multisig_k.erase(mk_it); +- else +- ++mk_it; + MDEBUG("Background keys file not found, restoring"); + store_background_keys(m_custom_background_key.get()); -+ } -+ + } +- } + +- cryptonote::block genesis; +- generate_genesis(genesis); +- crypto::hash genesis_hash = get_block_hash(genesis); + if (!background_wallet_exists) + { + MDEBUG("Background cache not found, restoring"); + store_background_cache(m_custom_background_key.get(), true/*do_reset_background_sync_data*/); + return; + } -+ + +- if (m_blockchain.empty()) +- { +- m_blockchain.push_back(genesis_hash); +- m_last_block_reward = cryptonote::get_outs_money_amount(genesis.miner_tx); +- } +- else +- { +- check_genesis(genesis_hash); +- } + MDEBUG("Loading background cache"); -+ + +- trim_hashchain(); + // Set up a minimal background wallet2 instance + std::unique_ptr background_w2(new wallet2(m_nettype)); + background_w2->m_is_background_wallet = true; + background_w2->m_background_syncing = true; + background_w2->m_background_sync_type = m_background_sync_type; + background_w2->m_custom_background_key = m_custom_background_key; -+ + +- if (get_num_subaddress_accounts() == 0) +- add_subaddress_account(tr("Primary account")); + cryptonote::account_base account = m_account; + account.forget_spend_key(); + background_w2->m_account = account; -+ + +- try +- { +- find_and_save_rings(false); +- } +- catch (const std::exception &e) +- { +- MERROR("Failed to save rings, will try again next time"); +- } +- +- try +- { +- if (use_fs) +- m_message_store.read_from_file(get_multisig_wallet_state(), m_mms_file, m_load_deprecated_formats); + // Load background cache from file + background_w2->clear(); + background_w2->prepare_file_names(background_wallet_file); @@ -2094,36 +2231,25 @@ index e4e02c782..618c43cee 100644 + + // Reset the background cache after processing + store_background_cache(m_custom_background_key.get(), true/*do_reset_background_sync_data*/); -+ } else { -+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, "unknown background sync type"); -+ } -+} -+//---------------------------------------------------------------------------------------------------- -+void wallet2::load_wallet_cache(const bool use_fs, const std::string& cache_buf) -+{ -+ boost::system::error_code e; - bool cache_missing = use_fs ? (!boost::filesystem::exists(m_wallet_file, e) || e) : cache_buf.empty(); - if (cache_missing) + } +- catch (const std::exception &e) ++ else { -@@ -6205,7 +6610,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass - bool r = true; - if (use_fs) - { -- load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits::max()); -+ r = load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits::max()); - THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, m_wallet_file); - } +- MERROR("Failed to initialize MMS, it will be unusable"); ++ THROW_WALLET_EXCEPTION(error::wallet_internal_error, "unknown background sync type"); + } + } + //---------------------------------------------------------------------------------------------------- +@@ -6443,6 +6838,8 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas + same_file = canonical_old_path == canonical_new_path; + } -@@ -6218,7 +6623,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass - THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "internal error: failed to deserialize \"" + m_wallet_file + '\"'); - std::string cache_data; - cache_data.resize(cache_file_data.cache_data.size()); -- crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), m_cache_key, cache_file_data.iv, &cache_data[0]); -+ crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), get_cache_key(), cache_file_data.iv, &cache_data[0]); ++ THROW_WALLET_EXCEPTION_IF(m_is_background_wallet && !same_file, error::wallet_internal_error, ++ "Cannot save background wallet files to a different location"); - try { - bool loaded = false; -@@ -6459,6 +6864,21 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas + if (!same_file) + { +@@ -6459,6 +6856,21 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas } } } @@ -2145,7 +2271,7 @@ index e4e02c782..618c43cee 100644 // get wallet cache data boost::optional cache_file_data = get_cache_file_data(); -@@ -6552,6 +6972,22 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas +@@ -6552,6 +6964,22 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas // store should only exist if the MMS is really active m_message_store.write_to_file(get_multisig_wallet_state(), m_mms_file); } @@ -2168,7 +2294,7 @@ index e4e02c782..618c43cee 100644 } //---------------------------------------------------------------------------------------------------- boost::optional wallet2::get_cache_file_data() -@@ -6569,7 +7005,7 @@ boost::optional wallet2::get_cache_file_data() +@@ -6569,7 +6997,7 @@ boost::optional wallet2::get_cache_file_data() std::string cipher; cipher.resize(cache_file_data.get().cache_data.size()); cache_file_data.get().iv = crypto::rand(); @@ -2177,7 +2303,7 @@ index e4e02c782..618c43cee 100644 cache_file_data.get().cache_data = cipher; return cache_file_data; } -@@ -8645,6 +9081,34 @@ bool wallet2::is_keys_file_locked() const +@@ -8645,6 +9073,34 @@ bool wallet2::is_keys_file_locked() const return m_keys_file_locker->locked(); } @@ -2212,7 +2338,7 @@ index e4e02c782..618c43cee 100644 bool wallet2::tx_add_fake_output(std::vector> &outs, uint64_t global_index, const crypto::public_key& output_public_key, const rct::key& mask, uint64_t real_index, bool unlocked, std::unordered_set &valid_public_keys_cache) const { if (!unlocked) // don't add locked outs -@@ -13980,6 +14444,408 @@ bool wallet2::import_key_images(signed_tx_set & signed_tx, size_t offset, bool o +@@ -13980,6 +14436,413 @@ bool wallet2::import_key_images(signed_tx_set & signed_tx, size_t offset, bool o return import_key_images(signed_tx.key_images, offset, only_selected_transfers ? boost::make_optional(selected_transfers) : boost::none); } @@ -2295,9 +2421,9 @@ index e4e02c782..618c43cee 100644 + // Sort background synced txs in the order they appeared in the cache so that + // we process them in the order they appeared in the chain. Thus if tx2 spends + // from tx1, we will know because tx1 is processed before tx2. -+ std::vector> sorted_bgs_cache(background_sync_data.txs.begin(), background_sync_data.txs.end()); ++ std::vector> sorted_bgs_cache(background_sync_data.txs.begin(), background_sync_data.txs.end()); + std::sort(sorted_bgs_cache.begin(), sorted_bgs_cache.end(), -+ [](const std::pair& l, const std::pair& r) ++ [](const std::pair& l, const std::pair& r) + { + uint64_t left_index = l.second.index_in_background_sync_data; + uint64_t right_index = r.second.index_in_background_sync_data; @@ -2360,6 +2486,8 @@ index e4e02c782..618c43cee 100644 + + THROW_WALLET_EXCEPTION_IF(m_background_sync_type != BackgroundSyncCustomPassword, error::wallet_internal_error, + "Can only write a background cache when using a custom background password"); ++ THROW_WALLET_EXCEPTION_IF(m_wallet_file.empty(), error::wallet_internal_error, ++ "No wallet file known, can't store background cache"); + + std::unique_ptr background_w2(new wallet2(m_nettype)); + background_w2->prepare_file_names(make_background_wallet_file_name(m_wallet_file)); @@ -2398,6 +2526,9 @@ index e4e02c782..618c43cee 100644 +{ + MDEBUG("Storing background keys"); + ++ THROW_WALLET_EXCEPTION_IF(m_wallet_file.empty(), error::wallet_internal_error, ++ "No wallet file known, can't store background keys"); ++ + const std::string background_keys_file = make_background_keys_file_name(m_wallet_file); + bool r = store_keys(background_keys_file, custom_background_key, false/*watch_only*/, true/*background_keys_file*/); + THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, background_keys_file); @@ -2622,7 +2753,7 @@ index e4e02c782..618c43cee 100644 { payment_container payments; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h -index b540eff6b..bfe3a4f19 100644 +index b540eff6b..d37332dd1 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -257,6 +257,20 @@ private: @@ -2664,7 +2795,7 @@ index b540eff6b..bfe3a4f19 100644 END_SERIALIZE() }; -+ struct background_synced_tx ++ struct background_synced_tx_t + { + uint64_t index_in_background_sync_data; + cryptonote::transaction tx; @@ -2690,9 +2821,9 @@ index b540eff6b..bfe3a4f19 100644 + + struct background_sync_data_t + { -+ bool first_refresh_done; -+ uint64_t start_height; -+ serializable_unordered_map txs; ++ bool first_refresh_done = false; ++ uint64_t start_height = 0; ++ serializable_unordered_map txs; + + // Relevant wallet settings + uint64_t wallet_refresh_from_block_height; @@ -2733,31 +2864,39 @@ index b540eff6b..bfe3a4f19 100644 bool has_multisig_partial_key_images() const; bool has_unknown_key_images() const; bool get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase = std::string()) const; -@@ -1300,6 +1369,11 @@ private: +@@ -1300,11 +1369,17 @@ private: return; } a & m_has_ever_refreshed_from_node; -+ if ((m_background_sync_type == BackgroundSyncCustomPassword && m_is_background_wallet) || -+ (m_background_sync_type == BackgroundSyncReusePassword && !m_is_background_wallet)) ++ if(ver < 31) + { -+ a & m_background_sync_data; ++ m_background_sync_data = background_sync_data_t{}; ++ return; + } ++ a & m_background_sync_data; } BEGIN_SERIALIZE_OBJECT() -@@ -1336,6 +1410,11 @@ private: + MAGIC_FIELD("monero wallet cache") +- VERSION_FIELD(1) ++ VERSION_FIELD(2) + FIELD(m_blockchain) + FIELD(m_transfers) + FIELD(m_account_public_address) +@@ -1336,6 +1411,12 @@ private: return true; } FIELD(m_has_ever_refreshed_from_node) -+ if ((m_background_sync_type == BackgroundSyncCustomPassword && m_is_background_wallet) || -+ (m_background_sync_type == BackgroundSyncReusePassword && !m_is_background_wallet)) ++ if (version < 2) + { -+ FIELD(m_background_sync_data) ++ m_background_sync_data = background_sync_data_t{}; ++ return true; + } ++ FIELD(m_background_sync_data) END_SERIALIZE() /*! -@@ -1351,6 +1430,8 @@ private: +@@ -1351,6 +1432,8 @@ private: * \return Whether path is valid format */ static bool wallet_valid_path_format(const std::string& file_path); @@ -2766,7 +2905,7 @@ index b540eff6b..bfe3a4f19 100644 static bool parse_long_payment_id(const std::string& payment_id_str, crypto::hash& payment_id); static bool parse_short_payment_id(const std::string& payment_id_str, crypto::hash8& payment_id); static bool parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id); -@@ -1399,6 +1480,9 @@ private: +@@ -1399,6 +1482,9 @@ private: void ignore_outputs_below(uint64_t value) { m_ignore_outputs_below = value; } bool track_uses() const { return m_track_uses; } void track_uses(bool value) { m_track_uses = value; } @@ -2776,15 +2915,7 @@ index b540eff6b..bfe3a4f19 100644 bool show_wallet_name_when_locked() const { return m_show_wallet_name_when_locked; } void show_wallet_name_when_locked(bool value) { m_show_wallet_name_when_locked = value; } BackgroundMiningSetupType setup_background_mining() const { return m_setup_background_mining; } -@@ -1425,6 +1509,7 @@ private: - void enable_multisig(bool enable) { m_enable_multisig = enable; } - bool is_mismatched_daemon_version_allowed() const { return m_allow_mismatched_daemon_version; } - void allow_mismatched_daemon_version(bool allow_mismatch) { m_allow_mismatched_daemon_version = allow_mismatch; } -+ uint64_t kdf_rounds() const { return m_kdf_rounds; }; - - bool get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector &additional_tx_keys) const; - void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys, const boost::optional &single_destination_subaddress = boost::none); -@@ -1714,6 +1799,9 @@ private: +@@ -1714,6 +1800,9 @@ private: uint64_t get_bytes_sent() const; uint64_t get_bytes_received() const; @@ -2794,7 +2925,7 @@ index b540eff6b..bfe3a4f19 100644 // MMS ------------------------------------------------------------------------------------------------- mms::message_store& get_message_store() { return m_message_store; }; const mms::message_store& get_message_store() const { return m_message_store; }; -@@ -1749,6 +1837,9 @@ private: +@@ -1749,6 +1838,9 @@ private: * \return Whether it was successful. */ bool store_keys(const std::string& keys_file_name, const epee::wipeable_string& password, bool watch_only = false); @@ -2804,7 +2935,7 @@ index b540eff6b..bfe3a4f19 100644 /*! * \brief Load wallet keys information from wallet file. * \param keys_file_name Name of wallet file -@@ -1762,6 +1853,7 @@ private: +@@ -1762,6 +1854,7 @@ private: */ bool load_keys_buf(const std::string& keys_buf, const epee::wipeable_string& password); bool load_keys_buf(const std::string& keys_buf, const epee::wipeable_string& password, boost::optional& keys_to_encrypt); @@ -2812,15 +2943,23 @@ index b540eff6b..bfe3a4f19 100644 void process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map, size_t> *output_tracker_cache = NULL, bool ignore_callbacks = false); bool should_skip_block(const cryptonote::block &b, uint64_t height) const; void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const parsed_block &parsed_block, const crypto::hash& bl_id, uint64_t height, const std::vector &tx_cache_data, size_t tx_cache_data_offset, std::map, size_t> *output_tracker_cache = NULL); -@@ -1770,6 +1862,7 @@ private: +@@ -1770,6 +1863,15 @@ private: void get_short_chain_history(std::list& ids, uint64_t granularity = 1) const; bool clear(); void clear_soft(bool keep_key_images=false); ++ /* ++ * clear_user_data clears data created by the user, which is mostly data ++ * that a view key cannot identify on chain. This function was initially ++ * added to ensure that a "background" wallet (a wallet that syncs with just ++ * a view key hot in memory) does not have any sensitive data loaded that it ++ * does not need in order to sync. Future devs should take care to ensure ++ * that this function deletes data that is not useful for background syncing ++ */ + void clear_user_data(); void pull_blocks(bool first, bool try_incremental, uint64_t start_height, uint64_t& blocks_start_height, const std::list &short_chain_history, std::vector &blocks, std::vector &o_indices, uint64_t ¤t_height); void pull_hashes(uint64_t start_height, uint64_t& blocks_start_height, const std::list &short_chain_history, std::vector &hashes); void fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list &short_chain_history, bool force = false); -@@ -1821,10 +1914,23 @@ private: +@@ -1821,10 +1923,23 @@ private: bool get_ring(const crypto::chacha_key &key, const crypto::key_image &key_image, std::vector &outs); crypto::chacha_key get_ringdb_key(); void setup_keys(const epee::wipeable_string &password); @@ -2844,19 +2983,16 @@ index b540eff6b..bfe3a4f19 100644 void register_devices(); hw::device& lookup_device(const std::string & device_descriptor); -@@ -1940,6 +2046,11 @@ private: +@@ -1940,6 +2055,8 @@ private: uint64_t m_ignore_outputs_above; uint64_t m_ignore_outputs_below; bool m_track_uses; + bool m_is_background_wallet; + BackgroundSyncType m_background_sync_type; -+ bool m_background_syncing; -+ bool m_processing_background_cache; -+ background_sync_data_t m_background_sync_data; bool m_show_wallet_name_when_locked; uint32_t m_inactivity_lock_timeout; BackgroundMiningSetupType m_setup_background_mining; -@@ -1985,6 +2096,7 @@ private: +@@ -1985,6 +2102,7 @@ private: uint64_t m_last_block_reward; std::unique_ptr m_keys_file_locker; @@ -2864,7 +3000,7 @@ index b540eff6b..bfe3a4f19 100644 mms::message_store m_message_store; bool m_original_keys_available; -@@ -1992,6 +2104,7 @@ private: +@@ -1992,6 +2110,7 @@ private: crypto::secret_key m_original_view_secret_key; crypto::chacha_key m_cache_key; @@ -2872,22 +3008,37 @@ index b540eff6b..bfe3a4f19 100644 std::shared_ptr m_encrypt_keys_after_refresh; bool m_unattended; -@@ -2025,6 +2138,8 @@ BOOST_CLASS_VERSION(tools::wallet2::signed_tx_set, 1) +@@ -2007,9 +2126,13 @@ private: + + static boost::mutex default_daemon_address_lock; + static std::string default_daemon_address; ++ ++ bool m_background_syncing; ++ bool m_processing_background_cache; ++ background_sync_data_t m_background_sync_data; + }; + } +-BOOST_CLASS_VERSION(tools::wallet2, 30) ++BOOST_CLASS_VERSION(tools::wallet2, 31) + BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 12) + BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1) + BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0) +@@ -2025,6 +2148,8 @@ BOOST_CLASS_VERSION(tools::wallet2::signed_tx_set, 1) BOOST_CLASS_VERSION(tools::wallet2::tx_construction_data, 4) BOOST_CLASS_VERSION(tools::wallet2::pending_tx, 3) BOOST_CLASS_VERSION(tools::wallet2::multisig_sig, 1) -+BOOST_CLASS_VERSION(tools::wallet2::background_synced_tx, 0) ++BOOST_CLASS_VERSION(tools::wallet2::background_synced_tx_t, 0) +BOOST_CLASS_VERSION(tools::wallet2::background_sync_data_t, 0) namespace boost { -@@ -2523,6 +2638,29 @@ namespace boost +@@ -2523,6 +2648,29 @@ namespace boost return; a & x.multisig_sigs; } + + template -+ inline void serialize(Archive& a, tools::wallet2::background_synced_tx &x, const boost::serialization::version_type ver) ++ inline void serialize(Archive& a, tools::wallet2::background_synced_tx_t &x, const boost::serialization::version_type ver) + { + a & x.index_in_background_sync_data; + a & x.tx; @@ -3537,7 +3688,7 @@ index 734229380..b964036bd 100644 +#define WALLET_RPC_ERROR_CODE_IS_BACKGROUND_WALLET -49 +#define WALLET_RPC_ERROR_CODE_IS_BACKGROUND_SYNCING -50 diff --git a/tests/functional_tests/transfer.py b/tests/functional_tests/transfer.py -index 4063911f4..39ee86df3 100755 +index 4063911f4..60eb09a10 100755 --- a/tests/functional_tests/transfer.py +++ b/tests/functional_tests/transfer.py @@ -30,6 +30,7 @@ @@ -3575,19 +3726,28 @@ index 4063911f4..39ee86df3 100755 def reset(self): print('Resetting blockchain') -@@ -71,6 +85,387 @@ class TransferTest(): - daemon.pop_blocks(res.height - 1) - daemon.flush_txpool() +@@ -840,12 +854,6 @@ class TransferTest(): + + print('Testing scan_tx') + +- def diff_transfers(actual_transfers, expected_transfers): +- diff = DeepDiff(actual_transfers, expected_transfers) +- if diff != {}: +- pp.pprint(diff) +- assert diff == {} +- + # set up sender_wallet + sender_wallet = self.wallet[0] + try: sender_wallet.close_wallet() +@@ -1127,5 +1135,385 @@ class TransferTest(): + except AssertionError: + pass + def check_background_sync(self): + daemon = Daemon() + + print('Testing background sync') + -+ # Background sync type options -+ REUSE_PASSWORD = 'reuse-wallet-password' -+ CUSTOM_PASSWORD = 'custom-background-password' -+ + # Some helper functions + def stop_with_wrong_inputs(wallet, wallet_password, seed = ''): + invalid = False @@ -3634,6 +3794,10 @@ index 4063911f4..39ee86df3 100755 + out_len = 0 if 'out' not in res else len(res.out) + sender_starting_balance = sender_wallet.get_balance().balance + ++ # Background sync type options ++ reuse_password = sender_wallet.background_sync_options.reuse_password ++ custom_password = sender_wallet.background_sync_options.custom_password ++ + # set up receiver_wallet + receiver_wallet = self.wallet[1] + try: receiver_wallet.close_wallet() @@ -3658,7 +3822,7 @@ index 4063911f4..39ee86df3 100755 + expected_receiver_balance = receiver_starting_balance + (amount - fee) + + print('Checking background sync on outgoing wallet') -+ sender_wallet.setup_background_sync(background_sync_type = REUSE_PASSWORD) ++ sender_wallet.setup_background_sync(background_sync_type = reuse_password) + sender_wallet.start_background_sync() + # Mine block to an uninvolved wallet + daemon.generateblocks('46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', 1) @@ -3683,7 +3847,7 @@ index 4063911f4..39ee86df3 100755 + + # Restore and check background syncing outgoing wallet + restore_wallet(sender_wallet, seeds[0]) -+ sender_wallet.setup_background_sync(background_sync_type = REUSE_PASSWORD) ++ sender_wallet.setup_background_sync(background_sync_type = reuse_password) + sender_wallet.start_background_sync() + sender_wallet.refresh() + for i, out_tx in enumerate(transfers.out): @@ -3709,9 +3873,9 @@ index 4063911f4..39ee86df3 100755 + assert_correct_transfers(sender_wallet, transfers, incoming_transfers, expected_sender_balance) + + # Check stopping a wallet with wallet files saved to disk -+ for background_sync_type in [REUSE_PASSWORD, CUSTOM_PASSWORD]: ++ for background_sync_type in [reuse_password, custom_password]: + restore_wallet(sender_wallet, seeds[0], 'test1', 'test_password') -+ background_cache_password = None if background_sync_type == REUSE_PASSWORD else 'background_password' ++ background_cache_password = None if background_sync_type == reuse_password else 'background_password' + sender_wallet.setup_background_sync(background_sync_type = background_sync_type, wallet_password = 'test_password', background_cache_password = background_cache_password) + sender_wallet.start_background_sync() + sender_wallet.refresh() @@ -3721,9 +3885,9 @@ index 4063911f4..39ee86df3 100755 + assert_correct_transfers(sender_wallet, transfers, incoming_transfers, expected_sender_balance) + + # Close wallet while background syncing, then reopen -+ for background_sync_type in [REUSE_PASSWORD, CUSTOM_PASSWORD]: ++ for background_sync_type in [reuse_password, custom_password]: + restore_wallet(sender_wallet, seeds[0], 'test1', 'test_password') -+ background_cache_password = None if background_sync_type == REUSE_PASSWORD else 'background_password' ++ background_cache_password = None if background_sync_type == reuse_password else 'background_password' + sender_wallet.setup_background_sync(background_sync_type = background_sync_type, wallet_password = 'test_password', background_cache_password = background_cache_password) + sender_wallet.start_background_sync() + sender_wallet.refresh() @@ -3735,9 +3899,9 @@ index 4063911f4..39ee86df3 100755 + assert_correct_transfers(sender_wallet, transfers, incoming_transfers, expected_sender_balance) + + # Close wallet while syncing normally, then reopen -+ for background_sync_type in [REUSE_PASSWORD, CUSTOM_PASSWORD]: ++ for background_sync_type in [reuse_password, custom_password]: + restore_wallet(sender_wallet, seeds[0], 'test1', 'test_password') -+ background_cache_password = None if background_sync_type == REUSE_PASSWORD else 'background_password' ++ background_cache_password = None if background_sync_type == reuse_password else 'background_password' + sender_wallet.setup_background_sync(background_sync_type = background_sync_type, wallet_password = 'test_password', background_cache_password = background_cache_password) + sender_wallet.refresh() + assert_correct_transfers(sender_wallet, transfers, incoming_transfers, expected_sender_balance) @@ -3751,7 +3915,7 @@ index 4063911f4..39ee86df3 100755 + restore_wallet(sender_wallet, seeds[0], 'test1', 'test_password') + assert not util_resources.file_exists('test1.background') + assert not util_resources.file_exists('test1.background.keys') -+ sender_wallet.setup_background_sync(background_sync_type = CUSTOM_PASSWORD, wallet_password = 'test_password', background_cache_password = background_cache_password) ++ sender_wallet.setup_background_sync(background_sync_type = custom_password, wallet_password = 'test_password', background_cache_password = background_cache_password) + assert util_resources.file_exists('test1.background') + assert util_resources.file_exists('test1.background.keys') + sender_wallet.close_wallet() @@ -3777,18 +3941,18 @@ index 4063911f4..39ee86df3 100755 + assert not util_resources.file_exists('test1.background') + assert not util_resources.file_exists('test1.background.keys') + same_password = False -+ try: sender_wallet.setup_background_sync(background_sync_type = CUSTOM_PASSWORD, wallet_password = 'test_password', background_cache_password = 'test_password') ++ try: sender_wallet.setup_background_sync(background_sync_type = custom_password, wallet_password = 'test_password', background_cache_password = 'test_password') + except: same_password = True + assert same_password + assert not util_resources.file_exists('test1.background') + assert not util_resources.file_exists('test1.background.keys') + + # Turn off background sync -+ for background_sync_type in [REUSE_PASSWORD, CUSTOM_PASSWORD]: ++ for background_sync_type in [reuse_password, custom_password]: + restore_wallet(sender_wallet, seeds[0], 'test1', 'test_password') -+ background_cache_password = None if background_sync_type == REUSE_PASSWORD else 'background_password' ++ background_cache_password = None if background_sync_type == reuse_password else 'background_password' + sender_wallet.setup_background_sync(background_sync_type = background_sync_type, wallet_password = 'test_password', background_cache_password = background_cache_password) -+ if background_sync_type == CUSTOM_PASSWORD: ++ if background_sync_type == custom_password: + assert util_resources.file_exists('test1.background') + assert util_resources.file_exists('test1.background.keys') + sender_wallet.close_wallet() @@ -3801,7 +3965,7 @@ index 4063911f4..39ee86df3 100755 + assert not util_resources.file_exists('test1.background') + assert not util_resources.file_exists('test1.background.keys') + sender_wallet.open_wallet('test1', password = 'test_password') -+ sender_wallet.setup_background_sync(background_sync_type = 'off', wallet_password = 'test_password') ++ sender_wallet.setup_background_sync(background_sync_type = sender_wallet.background_sync_options.off, wallet_password = 'test_password') + assert not util_resources.file_exists('test1.background') + assert not util_resources.file_exists('test1.background.keys') + sender_wallet.close_wallet() @@ -3816,7 +3980,7 @@ index 4063911f4..39ee86df3 100755 + assert_correct_transfers(sender_wallet, transfers, incoming_transfers, expected_sender_balance) + + print('Checking background sync on incoming wallet') -+ receiver_wallet.setup_background_sync(background_sync_type = REUSE_PASSWORD) ++ receiver_wallet.setup_background_sync(background_sync_type = reuse_password) + receiver_wallet.start_background_sync() + receiver_wallet.refresh() + transfers = receiver_wallet.get_transfers() @@ -3834,7 +3998,7 @@ index 4063911f4..39ee86df3 100755 + + # Restore and check background syncing incoming wallet + restore_wallet(receiver_wallet, seeds[1]) -+ receiver_wallet.setup_background_sync(background_sync_type = REUSE_PASSWORD) ++ receiver_wallet.setup_background_sync(background_sync_type = reuse_password) + receiver_wallet.start_background_sync() + receiver_wallet.refresh() + if 'out' in transfers: @@ -3861,7 +4025,7 @@ index 4063911f4..39ee86df3 100755 + + # Check a fresh incoming wallet with wallet files saved to disk and encrypted with password + restore_wallet(receiver_wallet, seeds[1], 'test2', 'test_password') -+ receiver_wallet.setup_background_sync(background_sync_type = REUSE_PASSWORD, wallet_password = 'test_password') ++ receiver_wallet.setup_background_sync(background_sync_type = reuse_password, wallet_password = 'test_password') + receiver_wallet.start_background_sync() + receiver_wallet.refresh() + assert_correct_transfers(receiver_wallet, background_transfers, background_incoming_transfers, background_bal) @@ -3871,7 +4035,7 @@ index 4063911f4..39ee86df3 100755 + + # Close receiver's wallet while background sync is enabled then reopen + restore_wallet(receiver_wallet, seeds[1], 'test2', 'test_password') -+ receiver_wallet.setup_background_sync(background_sync_type = REUSE_PASSWORD, wallet_password = 'test_password') ++ receiver_wallet.setup_background_sync(background_sync_type = reuse_password, wallet_password = 'test_password') + receiver_wallet.start_background_sync() + receiver_wallet.refresh() + diff_transfers(receiver_wallet.get_transfers(), background_transfers) @@ -3904,12 +4068,12 @@ index 4063911f4..39ee86df3 100755 + daemon.out_peers(0) + + # Background sync type options -+ REUSE_PASSWORD = 'reuse-wallet-password' -+ CUSTOM_PASSWORD = 'custom-background-password' ++ sender_wallet = self.wallet[0] ++ reuse_password = sender_wallet.background_sync_options.reuse_password ++ custom_password = sender_wallet.background_sync_options.custom_password + -+ for background_sync_type in [REUSE_PASSWORD, CUSTOM_PASSWORD]: ++ for background_sync_type in [reuse_password, custom_password]: + # Set up wallet saved to disk -+ sender_wallet = self.wallet[0] + sender_wallet.close_wallet() + util_resources.remove_wallet_files('test1') + sender_wallet.restore_deterministic_wallet(seed = seeds[0], filename = 'test1', password = '') @@ -3937,7 +4101,7 @@ index 4063911f4..39ee86df3 100755 + assert sender_wallet.get_balance().balance < (sender_starting_balance - amount) + + # Pop the block while background syncing -+ background_cache_password = None if background_sync_type == REUSE_PASSWORD else 'background_password' ++ background_cache_password = None if background_sync_type == reuse_password else 'background_password' + sender_wallet.setup_background_sync(background_sync_type = background_sync_type, wallet_password = '', background_cache_password = background_cache_password) + sender_wallet.start_background_sync() + daemon.pop_blocks(1) @@ -3959,25 +4123,10 @@ index 4063911f4..39ee86df3 100755 + self.wallet[0].close_wallet() + self.wallet[0].restore_deterministic_wallet(seed = seeds[0]) + -+ - def create(self): - print('Creating wallets') - self.wallet = [None] * len(seeds) -@@ -840,12 +1235,6 @@ class TransferTest(): - - print('Testing scan_tx') - -- def diff_transfers(actual_transfers, expected_transfers): -- diff = DeepDiff(actual_transfers, expected_transfers) -- if diff != {}: -- pp.pprint(diff) -- assert diff == {} -- - # set up sender_wallet - sender_wallet = self.wallet[0] - try: sender_wallet.close_wallet() + if __name__ == '__main__': + TransferTest().run_test() diff --git a/tests/functional_tests/util_resources.py b/tests/functional_tests/util_resources.py -index e030312da..3197187f4 100755 +index e030312da..3ca6fdb86 100755 --- a/tests/functional_tests/util_resources.py +++ b/tests/functional_tests/util_resources.py @@ -37,6 +37,8 @@ @@ -4009,7 +4158,7 @@ index e030312da..3197187f4 100755 + return WALLET_DIRECTORY + '/' + name + +def remove_wallet_files(name): -+ for suffix in ['', '.keys', '.background', '.background.keys']: ++ for suffix in ['', '.keys', '.background', '.background.keys', '.address.txt']: + remove_file(name + suffix) + +def file_exists(name): @@ -4128,15 +4277,22 @@ index ef6964f9e..25121a02e 100644 + ASSERT_TRUE(str == std::string("foo")); +} diff --git a/utils/python-rpc/framework/wallet.py b/utils/python-rpc/framework/wallet.py -index 1e10e1f86..ccf6ca93e 100644 +index 1e10e1f86..bff33a561 100644 --- a/utils/python-rpc/framework/wallet.py +++ b/utils/python-rpc/framework/wallet.py -@@ -1138,3 +1138,38 @@ class Wallet(object): +@@ -1138,3 +1138,45 @@ class Wallet(object): 'id': '0' } return self.rpc.send_json_rpc_request(frozen) + -+ def setup_background_sync(self, background_sync_type = 'off', wallet_password = '', background_cache_password = ''): ++ class BackgroundSyncOptions(object): ++ def __init__(self): ++ self.off = 'off' ++ self.reuse_password = 'reuse-wallet-password' ++ self.custom_password = 'custom-background-password' ++ background_sync_options = BackgroundSyncOptions() ++ ++ def setup_background_sync(self, background_sync_type = background_sync_options.off, wallet_password = '', background_cache_password = ''): + setup_background_sync = { + 'method': 'setup_background_sync', + 'jsonrpc': '2.0', @@ -4170,3 +4326,6 @@ index 1e10e1f86..ccf6ca93e 100644 + 'id': '0' + } + return self.rpc.send_json_rpc_request(stop_background_sync) +-- +2.44.0 + diff --git a/patches/wownero/0003-airgap.patch b/patches/monero/0003-airgap.patch similarity index 77% rename from patches/wownero/0003-airgap.patch rename to patches/monero/0003-airgap.patch index e11310e..80bc18c 100644 --- a/patches/wownero/0003-airgap.patch +++ b/patches/monero/0003-airgap.patch @@ -1,21 +1,21 @@ -From 5c43c69b1a4821ed8a0c3cb8e33e164c2ac46d9a Mon Sep 17 00:00:00 2001 +From c325add45cf950a42fc4cc16f99bb7385c53a634 Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto -Date: Tue, 26 Mar 2024 09:06:32 +0100 -Subject: [PATCH] airgap +Date: Tue, 12 Mar 2024 10:09:50 +0100 +Subject: [PATCH 3/8] airgap --- - src/wallet/api/wallet.cpp | 23 +++++++++++++++++++++++ + src/wallet/api/wallet.cpp | 23 ++++++++++++++++++++++ src/wallet/api/wallet.h | 2 ++ src/wallet/api/wallet2_api.h | 3 +++ - src/wallet/wallet2.cpp | 28 ++++++++++++++++++++++------ + src/wallet/wallet2.cpp | 38 ++++++++++++++++++++++++++++++------ src/wallet/wallet2.h | 1 + - 5 files changed, 51 insertions(+), 6 deletions(-) + 5 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp -index 1f3bf4ab7..63ed26a11 100644 +index 1a9c6f674..42887dced 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp -@@ -1172,6 +1172,24 @@ uint64_t WalletImpl::unlockedBalance(uint32_t accountIndex) const +@@ -1129,6 +1129,24 @@ uint64_t WalletImpl::unlockedBalance(uint32_t accountIndex) const return m_wallet->unlocked_balance(accountIndex, false); } @@ -40,7 +40,7 @@ index 1f3bf4ab7..63ed26a11 100644 uint64_t WalletImpl::blockChainHeight() const { if(m_wallet->light_wallet()) { -@@ -1376,6 +1394,11 @@ bool WalletImpl::submitTransaction(const string &fileName) { +@@ -1291,6 +1309,11 @@ bool WalletImpl::submitTransaction(const string &fileName) { return true; } @@ -53,10 +53,10 @@ index 1f3bf4ab7..63ed26a11 100644 { if (m_wallet->watch_only()) diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h -index 35c05ef5b..bc059699f 100644 +index 9acd2871f..05d065c5c 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h -@@ -130,6 +130,7 @@ public: +@@ -122,6 +122,7 @@ public: bool setProxy(const std::string &address) override; uint64_t balance(uint32_t accountIndex = 0) const override; uint64_t unlockedBalance(uint32_t accountIndex = 0) const override; @@ -64,19 +64,19 @@ index 35c05ef5b..bc059699f 100644 uint64_t blockChainHeight() const override; uint64_t approximateBlockChainHeight() const override; uint64_t estimateBlockChainHeight() const override; -@@ -190,6 +191,7 @@ public: +@@ -175,6 +176,7 @@ public: + virtual PendingTransaction * createSweepUnmixableTransaction() override; + bool submitTransaction(const std::string &fileName) override; virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override; - virtual UnsignedTransaction * loadUnsignedTxFromStr(const std::string &unsigned_tx) override; - virtual UnsignedTransaction * loadUnsignedTxFromBase64Str(const std::string &unsigned_tx) override; + bool hasUnknownKeyImages() const override; - virtual PendingTransaction * loadSignedTx(const std::string &signed_filename) override; bool exportKeyImages(const std::string &filename, bool all = false) override; bool importKeyImages(const std::string &filename) override; + bool exportOutputs(const std::string &filename, bool all = false) override; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h -index 648dc29b5..c2fa3d95b 100644 +index 4268b656e..4edaefefd 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h -@@ -726,6 +726,7 @@ struct Wallet +@@ -626,6 +626,7 @@ struct Wallet result += unlockedBalance(i); return result; } @@ -84,7 +84,7 @@ index 648dc29b5..c2fa3d95b 100644 /** * @brief watchOnly - checks if wallet is watch only -@@ -1045,6 +1046,8 @@ struct Wallet +@@ -910,6 +911,8 @@ struct Wallet virtual uint64_t estimateTransactionFee(const std::vector> &destinations, PendingTransaction::Priority priority) const = 0; @@ -94,10 +94,27 @@ index 648dc29b5..c2fa3d95b 100644 * \brief exportKeyImages - exports key images to file * \param filename diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp -index 56b76c5f9..00d9c133e 100644 +index c7cbdbbe6..700816da6 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp -@@ -7440,6 +7440,25 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t * +@@ -949,6 +949,16 @@ uint32_t get_subaddress_clamped_sum(uint32_t idx, uint32_t extra) + return idx + extra; + } + ++bool is_preferred_input(const std::vector& preferred_input_list, const crypto::key_image& input) { ++ if (!preferred_input_list.empty()) { ++ auto it = std::find(preferred_input_list.begin(), preferred_input_list.end(), input); ++ if (it == preferred_input_list.end()) { ++ return false; ++ } ++ } ++ return true; ++} ++ + static void setup_shim(hw::wallet_shim * shim, tools::wallet2 * wallet) + { + shim->get_tx_pub_key_from_received_outs = std::bind(&tools::wallet2::get_tx_pub_key_from_received_outs, wallet, std::placeholders::_1); +@@ -7037,6 +7047,25 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t * return amount; } //---------------------------------------------------------------------------------------------------- @@ -123,7 +140,7 @@ index 56b76c5f9..00d9c133e 100644 std::map wallet2::balance_per_subaddress(uint32_t index_major, bool strict) const { std::map amount_per_subaddr; -@@ -8290,9 +8309,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector additional_derivations; @@ -134,7 +151,7 @@ index 56b76c5f9..00d9c133e 100644 std::vector additional_tx_pub_keys; for (const crypto::secret_key &skey: txs[n].additional_tx_keys) { -@@ -11700,7 +11717,7 @@ std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_2(std::vector m_ignore_outputs_above || td.amount() < m_ignore_outputs_below) { -@@ -11750,8 +11767,7 @@ std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_2(std::vector balance_per_subaddress(uint32_t subaddr_index_major, bool strict) const; std::map>> unlocked_balance_per_subaddress(uint32_t subaddr_index_major, bool strict); +-- +2.44.0 + diff --git a/patches/monero/0003-coin-control.patch b/patches/monero/0004-coin-control.patch similarity index 97% rename from patches/monero/0003-coin-control.patch rename to patches/monero/0004-coin-control.patch index 2d25beb..8a26358 100644 --- a/patches/monero/0003-coin-control.patch +++ b/patches/monero/0004-coin-control.patch @@ -1,7 +1,7 @@ -From a95f52274d4a6a467e06bff60121850adba387ad Mon Sep 17 00:00:00 2001 +From fb9cd4ff500a56a1f29f323fe05de4633dd560de Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto Date: Tue, 12 Mar 2024 11:07:57 +0100 -Subject: [PATCH] PATCH: coin control +Subject: [PATCH 4/8] coin control --- src/wallet/api/CMakeLists.txt | 8 +- @@ -717,10 +717,10 @@ index 4edaefefd..8a5c4135e 100644 virtual SubaddressAccount * subaddressAccount() = 0; virtual void setListener(WalletListener *) = 0; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp -index 3477e084f..c3376f7e0 100644 +index 700816da6..5331f90fc 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp -@@ -2081,12 +2081,21 @@ bool wallet2::frozen(const multisig_tx_set& txs) const +@@ -2083,12 +2083,21 @@ bool wallet2::frozen(const multisig_tx_set& txs) const return false; } @@ -742,7 +742,7 @@ index 3477e084f..c3376f7e0 100644 void wallet2::thaw(const crypto::key_image &ki) { thaw(get_transfer_details(ki)); -@@ -2097,6 +2106,18 @@ bool wallet2::frozen(const crypto::key_image &ki) const +@@ -2099,6 +2108,18 @@ bool wallet2::frozen(const crypto::key_image &ki) const return frozen(get_transfer_details(ki)); } //---------------------------------------------------------------------------------------------------- @@ -761,7 +761,7 @@ index 3477e084f..c3376f7e0 100644 size_t wallet2::get_transfer_details(const crypto::key_image &ki) const { for (size_t idx = 0; idx < m_transfers.size(); ++idx) -@@ -2500,6 +2521,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote +@@ -2510,6 +2531,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote uint64_t amount = tx.vout[o].amount ? tx.vout[o].amount : tx_scan_info[o].amount; if (!pool) { @@ -769,7 +769,7 @@ index 3477e084f..c3376f7e0 100644 m_transfers.push_back(transfer_details{}); transfer_details& td = m_transfers.back(); td.m_block_height = height; -@@ -2603,6 +2625,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote +@@ -2613,6 +2635,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote uint64_t extra_amount = amount - burnt; if (!pool) { @@ -777,7 +777,7 @@ index 3477e084f..c3376f7e0 100644 transfer_details &td = m_transfers[kit->second]; td.m_block_height = height; td.m_internal_output_index = o; -@@ -10495,7 +10518,7 @@ void wallet2::transfer_selected_rct(std::vector picks; float current_output_relatdness = 1.0f; -@@ -10506,6 +10529,9 @@ std::vector wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui +@@ -10498,6 +10521,9 @@ std::vector wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details& td = m_transfers[i]; @@ -796,7 +796,7 @@ index 3477e084f..c3376f7e0 100644 if (!is_spent(td, false) && !td.m_frozen && td.is_rct() && td.amount() >= needed_money && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1) { if (td.amount() > m_ignore_outputs_above || td.amount() < m_ignore_outputs_below) -@@ -10526,6 +10552,9 @@ std::vector wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui +@@ -10518,6 +10544,9 @@ std::vector wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details& td = m_transfers[i]; @@ -806,7 +806,7 @@ index 3477e084f..c3376f7e0 100644 if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && td.is_rct() && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1) { if (td.amount() > m_ignore_outputs_above || td.amount() < m_ignore_outputs_below) -@@ -10537,6 +10566,9 @@ std::vector wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui +@@ -10529,6 +10558,9 @@ std::vector wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui for (size_t j = i + 1; j < m_transfers.size(); ++j) { const transfer_details& td2 = m_transfers[j]; @@ -816,7 +816,7 @@ index 3477e084f..c3376f7e0 100644 if (td2.amount() > m_ignore_outputs_above || td2.amount() < m_ignore_outputs_below) { MDEBUG("Ignoring output " << j << " of amount " << print_money(td2.amount()) << " which is outside prescribed range [" << print_money(m_ignore_outputs_below) << ", " << print_money(m_ignore_outputs_above) << "]"); -@@ -11109,7 +11141,7 @@ bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image, +@@ -11101,7 +11133,7 @@ bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image, // This system allows for sending (almost) the entire balance, since it does // not generate spurious change in all txes, thus decreasing the instantaneous // usable balance. @@ -825,7 +825,7 @@ index 3477e084f..c3376f7e0 100644 { //ensure device is let in NONE mode in any case hw::device &hwdev = m_account.get_device(); -@@ -11317,6 +11349,9 @@ std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_2(std::vector &ptx_vector, c +@@ -11874,7 +11909,7 @@ bool wallet2::sanity_check(const std::vector &ptx_vector, c return true; } @@ -853,7 +853,7 @@ index 3477e084f..c3376f7e0 100644 { std::vector unused_transfers_indices; std::vector unused_dust_indices; -@@ -11911,6 +11946,9 @@ std::vector wallet2::create_transactions_all(uint64_t below +@@ -11903,6 +11938,9 @@ std::vector wallet2::create_transactions_all(uint64_t below for (size_t i = 0; i < m_transfers.size(); ++i) { const transfer_details& td = m_transfers[i]; @@ -864,7 +864,7 @@ index 3477e084f..c3376f7e0 100644 { MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is below threshold " << print_money(fractional_threshold)); diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h -index 406acac2b..5eae908ad 100644 +index fc69b3d36..52886fb85 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -1207,8 +1207,8 @@ private: @@ -878,7 +878,7 @@ index 406acac2b..5eae908ad 100644 std::vector create_transactions_single(const crypto::key_image &ki, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra); std::vector create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector unused_transfers_indices, std::vector unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector& extra); bool sanity_check(const std::vector &ptx_vector, const std::vector& dsts, const unique_index_container& subtract_fee_from_outputs = {}) const; -@@ -1559,6 +1559,7 @@ private: +@@ -1560,6 +1560,7 @@ private: uint64_t get_num_rct_outputs(); size_t get_num_transfer_details() const { return m_transfers.size(); } const transfer_details &get_transfer_details(size_t idx) const; @@ -886,7 +886,7 @@ index 406acac2b..5eae908ad 100644 uint8_t get_current_hard_fork(); void get_hard_fork_info(uint8_t version, uint64_t &earliest_height); -@@ -1788,7 +1789,9 @@ private: +@@ -1789,7 +1790,9 @@ private: void freeze(size_t idx); void thaw(size_t idx); bool frozen(size_t idx) const; @@ -896,7 +896,7 @@ index 406acac2b..5eae908ad 100644 void thaw(const crypto::key_image &ki); bool frozen(const crypto::key_image &ki) const; bool frozen(const transfer_details &td) const; -@@ -1829,6 +1832,8 @@ private: +@@ -1830,6 +1833,8 @@ private: static std::string get_default_daemon_address() { CRITICAL_REGION_LOCAL(default_daemon_address_lock); return default_daemon_address; } @@ -905,7 +905,7 @@ index 406acac2b..5eae908ad 100644 private: /*! * \brief Stores wallet information to wallet file. -@@ -1892,7 +1897,7 @@ private: +@@ -1901,7 +1906,7 @@ private: std::vector get_unspent_amounts_vector(bool strict); uint64_t get_dynamic_base_fee_estimate(); float get_output_relatedness(const transfer_details &td0, const transfer_details &td1) const; @@ -914,3 +914,6 @@ index 406acac2b..5eae908ad 100644 void set_spent(size_t idx, uint64_t height); void set_unspent(size_t idx); bool is_spent(const transfer_details &td, bool strict = true) const; +-- +2.44.0 + diff --git a/patches/monero/0004-fix-build.patch b/patches/monero/0005-fix-build-issues.patch similarity index 97% rename from patches/monero/0004-fix-build.patch rename to patches/monero/0005-fix-build-issues.patch index e3d3566..f5e5f08 100644 --- a/patches/monero/0004-fix-build.patch +++ b/patches/monero/0005-fix-build-issues.patch @@ -1,7 +1,7 @@ -From 1a05393366d94819c83b5e6983cb44938ac06c67 Mon Sep 17 00:00:00 2001 +From 6bd41f6e334fe979e2a5e874e404657ff0ef6c4f Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto Date: Tue, 12 Mar 2024 17:59:13 +0100 -Subject: [PATCH] PATCH: fix build issues +Subject: [PATCH 5/8] fix build issues --- contrib/depends/hosts/linux.mk | 8 +++---- @@ -63,7 +63,7 @@ index d2d1eca85..8783d4955 100644 ifneq ($(GITIAN),1) diff --git a/contrib/depends/packages/polyseed.mk b/contrib/depends/packages/polyseed.mk new file mode 100644 -index 000000000..47a532907 +index 000000000..2ddeac621 --- /dev/null +++ b/contrib/depends/packages/polyseed.mk @@ -0,0 +1,23 @@ @@ -132,3 +132,6 @@ index 000000000..f05cb2b6a + #define POLYSEED_PRIVATE + #else + #ifdef POLYSEED_SHARED +-- +2.44.0 + diff --git a/patches/wownero/0006-macos-build-fix.patch b/patches/monero/0006-macos-build-fix.patch similarity index 97% rename from patches/wownero/0006-macos-build-fix.patch rename to patches/monero/0006-macos-build-fix.patch index 4149a02..4f7228f 100644 --- a/patches/wownero/0006-macos-build-fix.patch +++ b/patches/monero/0006-macos-build-fix.patch @@ -1,7 +1,7 @@ -From b1b150b3de4dd3197c373be39b790c31bb7ddab3 Mon Sep 17 00:00:00 2001 +From c8dfb421082c895c45c6e4fd1437fee4b554b612 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 28 Mar 2024 02:03:08 +0100 -Subject: [PATCH] macos build fix +Subject: [PATCH 6/8] macos build fix --- contrib/depends/hosts/darwin.mk | 2 + @@ -111,5 +111,5 @@ index 000000000..a261636e8 +2.39.2 + -- -2.39.2 +2.44.0 diff --git a/patches/monero/0006-fix-make-debug-test-target.patch b/patches/monero/0007-fix-make-debug-test-target.patch similarity index 95% rename from patches/monero/0006-fix-make-debug-test-target.patch rename to patches/monero/0007-fix-make-debug-test-target.patch index c376d98..1e3f708 100644 --- a/patches/monero/0006-fix-make-debug-test-target.patch +++ b/patches/monero/0007-fix-make-debug-test-target.patch @@ -1,7 +1,7 @@ -From c1af99f391626d567fec83210a945f6f60bea700 Mon Sep 17 00:00:00 2001 +From d0d86d333ea4788cc27c4c87c5ec2ec3bc1668b7 Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto Date: Tue, 2 Apr 2024 01:13:12 +0200 -Subject: [PATCH] fix `make debug-test` target +Subject: [PATCH 7/8] fix `make debug-test` target --- src/simplewallet/simplewallet.cpp | 4 ++-- diff --git a/patches/monero/0007-fix-missing-___clear_cache-when-targetting-iOS.patch b/patches/monero/0008-fix-missing-___clear_cache-when-targetting-iOS.patch similarity index 86% rename from patches/monero/0007-fix-missing-___clear_cache-when-targetting-iOS.patch rename to patches/monero/0008-fix-missing-___clear_cache-when-targetting-iOS.patch index cceb4e9..b4a14f9 100644 --- a/patches/monero/0007-fix-missing-___clear_cache-when-targetting-iOS.patch +++ b/patches/monero/0008-fix-missing-___clear_cache-when-targetting-iOS.patch @@ -1,7 +1,7 @@ -From 34ca1a796e55dcff448c882189a45dcb29d77566 Mon Sep 17 00:00:00 2001 +From b154719d3fe7ae407de91f5c5a245998efd05997 Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto Date: Tue, 2 Apr 2024 16:51:56 +0200 -Subject: [PATCH] fix missing ___clear_cache when targetting iOS +Subject: [PATCH 8/8] fix missing ___clear_cache when targetting iOS --- .gitmodules | 2 +- @@ -29,5 +29,5 @@ index 102f8acf9..ce72c9bb9 160000 -Subproject commit 102f8acf90a7649ada410de5499a7ec62e49e1da +Subproject commit ce72c9bb9cb799e0d9171094b9abb009e04c5bfc -- -2.39.2 +2.44.0 diff --git a/patches/monero/README.md b/patches/monero/README.md index 4aa33d1..b840515 100644 --- a/patches/monero/README.md +++ b/patches/monero/README.md @@ -1,35 +1,43 @@ -> 0000 to 0003 were created most likely by feather dev, anonero monero repository got nuked and now says that I made the changes, so I am unable to credit the original authors, http://git.anonero5wmhraxqsvzq2ncgptq6gq45qoto6fnkfwughfl4gbt44swad.onion/ANONERO/monero/commits/branch/v0.18.3.3-anonero +> 0001 to 0004 were created most likely by feather dev, anonero monero repository got nuked and now says that I made the changes, so I am unable to credit the original authors, http://git.anonero5wmhraxqsvzq2ncgptq6gq45qoto6fnkfwughfl4gbt44swad.onion/ANONERO/monero/commits/branch/v0.18.3.3-anonero -# 0000-polyseed +# 0001-polyseed -Polyseed support for wallets [planned in long distant future as a part of walet3 - not getting upstream, no PR available] +Polyseed support for wallets [planned in long distant future as a part of walet3 - not getting upstream, no PR available]. -# 0001-background-sync +Note, only English support is available due to issues with normalization libraries. -https://github.com/monero-project/monero/pull/8619 +> tobtoht: You may also want to reconsider supporting languages other than English: https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki#wordlists (this is about BIP39, but because unicode normalization is such a PITA it will become true for Polyseed wallets as well) -# 0002-airgap +Considering the fact that even Feather Wallet doesn't support non-english seeds, it makes sense to go that way. + +At least until (if ever) feather wallet supports multi-language polyseed seeds I don't think it is a good idea to support them, especially because of possible issues when targetting different platforms. + +# 0002-background-sync + +Sourced from: https://github.com/monero-project/monero/pull/8617, no changes except for merge conflicts. + +# 0003-airgap Cool functions for offline transactions -# 0003-coin-control +# 0004-coin-control Coin control patch, I was able to trace it's orgins back to wownero/monerujo. -# 0004-fix-build +# 0005-fix-build Fix cross compilation for linux -# 0005-macos-build-fix +# 0006-macos-build-fix Fixes cross compilation for MacOS targets -# 0006-fix-make-debug-test-target +# 0007-fix-make-debug-test-target I had some debugging to do, I don't remember actually why I decided to run the tests, but since it is a fix I've decided to leave it in here just in case. -# 0007-fix-missing-___clear_cache-when-targetting-iOS +# 0008-fix-missing-___clear_cache-when-targetting-iOS https://github.com/tevador/RandomX/pull/294 \ No newline at end of file diff --git a/patches/wownero/0000-fix-wallet_api-compilation-target.patch b/patches/wownero/0001-Fix-wallet_api-compilation-target-https-git.wownero..patch similarity index 92% rename from patches/wownero/0000-fix-wallet_api-compilation-target.patch rename to patches/wownero/0001-Fix-wallet_api-compilation-target-https-git.wownero..patch index 4ccc436..6a6c697 100644 --- a/patches/wownero/0000-fix-wallet_api-compilation-target.patch +++ b/patches/wownero/0001-Fix-wallet_api-compilation-target-https-git.wownero..patch @@ -1,7 +1,7 @@ -From e1b6d9158179fe7f21dc9caab4605cf82fc49db0 Mon Sep 17 00:00:00 2001 +From f0f386f43d6fc998c93ecb12666688d85a4d6fca Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto Date: Tue, 26 Mar 2024 06:55:38 +0100 -Subject: [PATCH] Fix wallet_api compilation target +Subject: [PATCH 1/9] Fix wallet_api compilation target https://git.wownero.com/wownero/wownero/issues/483 --- @@ -26,3 +26,6 @@ index 823f122c2..d81ddec93 100644 } pendingTxPostProcess(transaction); +-- +2.44.0 + diff --git a/patches/monero/0000-polyseed.patch b/patches/wownero/0002-polyseed-support.patch similarity index 92% rename from patches/monero/0000-polyseed.patch rename to patches/wownero/0002-polyseed-support.patch index 7513399..8c5c12e 100644 --- a/patches/monero/0000-polyseed.patch +++ b/patches/wownero/0002-polyseed-support.patch @@ -1,7 +1,7 @@ -From edd49593044dc861b5fb4b9bae56a7636199aeaf Mon Sep 17 00:00:00 2001 +From 33d611538efef134106f427c7ee5535d28d588f6 Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto -Date: Tue, 12 Mar 2024 09:42:37 +0100 -Subject: [PATCH] PATCH: polyseed +Date: Tue, 26 Mar 2024 08:19:23 +0100 +Subject: [PATCH 2/9] polyseed support --- .github/workflows/build.yml | 4 +- @@ -54,36 +54,36 @@ index 4c1e381c0..70bea03b3 100644 test-ubuntu: needs: build-ubuntu diff --git a/.gitmodules b/.gitmodules -index 721cce3b4..73a23fb35 100644 +index 74571d5ee..86009b6b6 100644 --- a/.gitmodules +++ b/.gitmodules -@@ -10,6 +10,12 @@ - [submodule "external/randomx"] - path = external/randomx - url = https://github.com/tevador/RandomX +@@ -12,6 +12,12 @@ + path = external/supercop + url = https://github.com/monero-project/supercop + branch = monero +[submodule "external/utf8proc"] + path = external/utf8proc + url = https://github.com/JuliaStrings/utf8proc.git +[submodule "external/polyseed"] + path = external/polyseed + url = https://github.com/tevador/polyseed.git - [submodule "external/supercop"] - path = external/supercop - url = https://github.com/monero-project/supercop + [submodule "external/randomwow"] + path = external/randomwow + url = https://git.wownero.com/wownero/RandomWOW diff --git a/CMakeLists.txt b/CMakeLists.txt -index 8fb03ba1f..63b8c5079 100644 +index 20829bc30..2dd427d3d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -369,6 +369,8 @@ if(NOT MANUAL_SUBMODULES) - check_submodule(external/trezor-common) - check_submodule(external/randomx) +@@ -370,6 +370,8 @@ if(NOT MANUAL_SUBMODULES) + #check_submodule(external/trezor-common) + check_submodule(external/randomwow) check_submodule(external/supercop) + check_submodule(external/polyseed) + check_submodule(external/utf8proc) endif() endif() -@@ -458,7 +460,7 @@ endif() +@@ -459,7 +461,7 @@ endif() # elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSDI.*") # set(BSDI TRUE) @@ -137,13 +137,13 @@ index b016f2f48..f2f365b1b 100644 + } diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt -index 5b7f69a56..1b9761d70 100644 +index 29aed0cc6..c023abffa 100644 --- a/external/CMakeLists.txt +++ b/external/CMakeLists.txt @@ -70,3 +70,5 @@ add_subdirectory(db_drivers) add_subdirectory(easylogging++) add_subdirectory(qrcodegen) - add_subdirectory(randomx EXCLUDE_FROM_ALL) + add_subdirectory(randomwow EXCLUDE_FROM_ALL) +add_subdirectory(polyseed EXCLUDE_FROM_ALL) +add_subdirectory(utf8proc EXCLUDE_FROM_ALL) \ No newline at end of file @@ -156,13 +156,13 @@ index 000000000..b7c35bb3c +Subproject commit b7c35bb3c6b91e481ecb04fc235eaff69c507fa1 diff --git a/external/utf8proc b/external/utf8proc new file mode 160000 -index 000000000..1cb28a66c +index 000000000..1fe43f5a6 --- /dev/null +++ b/external/utf8proc @@ -0,0 +1 @@ -+Subproject commit 1cb28a66ca79a0845e99433fd1056257456cef8b ++Subproject commit 1fe43f5a6d9c628f717c5ec8aeaeae4a9adfd167 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt -index 3335d3c21..06b708cf0 100644 +index 9216bcaa5..c043ba150 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -95,6 +95,7 @@ add_subdirectory(net) @@ -277,10 +277,10 @@ index 2ee9545d4..0099ebfe7 100644 const account_keys& get_keys() const; std::string get_public_address_str(network_type nettype) const; diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h -index 61146a114..8e1a07110 100644 +index 8c0d3ce20..1c1830ad4 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h -@@ -207,6 +207,8 @@ +@@ -219,6 +219,8 @@ #define DNS_BLOCKLIST_LIFETIME (86400 * 8) @@ -828,10 +828,10 @@ index 000000000..2c8c777a7 +#endif //POLYSEED_HPP \ No newline at end of file diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp -index 8d7364cba..472f05016 100644 +index d81ddec93..db9c2b5d9 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp -@@ -690,6 +690,28 @@ bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &p +@@ -683,6 +683,28 @@ bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &p return true; } @@ -860,7 +860,7 @@ index 8d7364cba..472f05016 100644 Wallet::Device WalletImpl::getDeviceType() const { return static_cast(m_wallet->get_device_type()); -@@ -798,6 +820,55 @@ std::string WalletImpl::seed(const std::string& seed_offset) const +@@ -820,6 +842,55 @@ std::string WalletImpl::seed(const std::string& seed_offset) const return std::string(seed.data(), seed.size()); // TODO } @@ -875,7 +875,7 @@ index 8d7364cba..472f05016 100644 + } + + bool result = m_wallet->get_polyseed(seed_words_epee, passphrase_epee); -+ ++ + seed_words.assign(seed_words_epee.data(), seed_words_epee.size()); + passphrase.assign(passphrase_epee.data(), passphrase_epee.size()); + @@ -897,7 +897,7 @@ index 8d7364cba..472f05016 100644 +bool Wallet::createPolyseed(std::string &seed_words, std::string &err, const std::string &language) +{ + epee::wipeable_string seed_words_epee(seed_words.c_str(), seed_words.size()); -+ ++ + try { + polyseed::data polyseed(POLYSEED_COIN); + polyseed.create(0); @@ -917,10 +917,10 @@ index 8d7364cba..472f05016 100644 { return m_wallet->get_seed_language(); diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h -index ec2d7e9b3..787215ab3 100644 +index 03b5a98e9..28135c82a 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h -@@ -79,9 +79,19 @@ public: +@@ -86,9 +86,19 @@ public: bool recoverFromDevice(const std::string &path, const std::string &password, const std::string &device_name); @@ -941,10 +941,10 @@ index ec2d7e9b3..787215ab3 100644 void setSeedLanguage(const std::string &arg) override; // void setListener(Listener *) {} diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h -index 71991df0d..9ea753083 100644 +index 6df661dc2..a0ed60a39 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h -@@ -700,6 +700,10 @@ struct Wallet +@@ -800,6 +800,10 @@ struct Wallet static void warning(const std::string &category, const std::string &str); static void error(const std::string &category, const std::string &str); @@ -955,7 +955,7 @@ index 71991df0d..9ea753083 100644 /** * @brief StartRefresh - Start/resume refresh thread (refresh every 10 seconds) */ -@@ -1256,6 +1260,27 @@ struct WalletManager +@@ -1432,6 +1436,27 @@ struct WalletManager uint64_t kdf_rounds = 1, WalletListener * listener = nullptr) = 0; @@ -984,10 +984,10 @@ index 71991df0d..9ea753083 100644 * \brief Closes wallet. In case operation succeeded, wallet object deleted. in case operation failed, wallet object not deleted * \param wallet previously opened / created wallet instance diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp -index e81b8f83a..c79fe25d6 100644 +index b166d8ac7..f88bd9e64 100644 --- a/src/wallet/api/wallet_manager.cpp +++ b/src/wallet/api/wallet_manager.cpp -@@ -156,6 +156,15 @@ Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path, +@@ -172,6 +172,15 @@ Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path, return wallet; } @@ -1004,10 +1004,10 @@ index e81b8f83a..c79fe25d6 100644 { WalletImpl * wallet_ = dynamic_cast(wallet); diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h -index a223e1df9..28fcd36c9 100644 +index 206aedc14..e3149300c 100644 --- a/src/wallet/api/wallet_manager.h +++ b/src/wallet/api/wallet_manager.h -@@ -75,6 +75,16 @@ public: +@@ -82,6 +82,16 @@ public: const std::string &subaddressLookahead = "", uint64_t kdf_rounds = 1, WalletListener * listener = nullptr) override; @@ -1025,7 +1025,7 @@ index a223e1df9..28fcd36c9 100644 bool walletExists(const std::string &path) override; bool verifyWalletPassword(const std::string &keys_file_name, const std::string &password, bool no_spend_key, uint64_t kdf_rounds = 1) const override; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp -index f34b10988..e4e02c782 100644 +index e586d67f7..83aba6253 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -92,6 +92,7 @@ using namespace epee; @@ -1036,17 +1036,17 @@ index f34b10988..e4e02c782 100644 extern "C" { -@@ -1260,7 +1261,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std +@@ -1272,7 +1273,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std m_enable_multisig(false), m_pool_info_query_time(0), m_has_ever_refreshed_from_node(false), -- m_allow_mismatched_daemon_version(false) -+ m_allow_mismatched_daemon_version(false), +- m_allow_mismatched_daemon_version(true) ++ m_allow_mismatched_daemon_version(true), + m_polyseed(false) { set_rpc_client_secret_key(rct::rct2sk(rct::skGen())); } -@@ -1438,10 +1440,25 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab +@@ -1450,10 +1452,25 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab key = cryptonote::encrypt_key(key, passphrase); if (!crypto::ElectrumWords::bytes_to_words(key, electrum_words, seed_language)) { @@ -1073,7 +1073,7 @@ index f34b10988..e4e02c782 100644 return true; } //---------------------------------------------------------------------------------------------------- -@@ -4629,6 +4646,9 @@ boost::optional wallet2::get_keys_file_data(const epee: +@@ -4712,6 +4729,9 @@ boost::optional wallet2::get_keys_file_data(const epee: value2.SetInt(m_enable_multisig ? 1 : 0); json.AddMember("enable_multisig", value2, json.GetAllocator()); @@ -1083,15 +1083,15 @@ index f34b10988..e4e02c782 100644 // Serialize the JSON object rapidjson::StringBuffer buffer; rapidjson::Writer writer(buffer); -@@ -4776,6 +4796,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st +@@ -4860,6 +4880,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_credits_target = 0; m_enable_multisig = false; - m_allow_mismatched_daemon_version = false; + m_allow_mismatched_daemon_version = true; + m_polyseed = false; } else if(json.IsObject()) { -@@ -5012,6 +5033,8 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st +@@ -5098,6 +5119,8 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_credits_target = field_credits_target; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, enable_multisig, int, Int, false, false); m_enable_multisig = field_enable_multisig; @@ -1100,7 +1100,7 @@ index f34b10988..e4e02c782 100644 } else { -@@ -5284,6 +5307,48 @@ void wallet2::init_type(hw::device::device_type device_type) +@@ -5370,6 +5393,48 @@ void wallet2::init_type(hw::device::device_type device_type) m_key_device_type = device_type; } @@ -1149,7 +1149,7 @@ index f34b10988..e4e02c782 100644 /*! * \brief Generates a wallet or restores one. Assumes the multisig setup * has already completed for the provided multisig info. -@@ -5411,7 +5476,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip +@@ -5497,7 +5562,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip return retval; } @@ -1158,7 +1158,7 @@ index f34b10988..e4e02c782 100644 { // -1 month for fluctuations in block time and machine date/time setup. // avg seconds per block -@@ -5435,7 +5500,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip +@@ -5521,7 +5586,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip // the daemon is currently syncing. // If we use the approximate height we subtract one month as // a safety margin. @@ -1167,65 +1167,60 @@ index f34b10988..e4e02c782 100644 uint64_t target_height = get_daemon_blockchain_target_height(err); if (err.empty()) { if (target_height < height) -@@ -13135,7 +13200,7 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err) +@@ -13546,9 +13611,9 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err) return target_height; } -uint64_t wallet2::get_approximate_blockchain_height() const +uint64_t wallet2::get_approximate_blockchain_height(uint64_t t) const { - // time of v2 fork - const time_t fork_time = m_nettype == TESTNET ? 1448285909 : m_nettype == STAGENET ? 1520937818 : 1458748658; -@@ -13144,7 +13209,7 @@ uint64_t wallet2::get_approximate_blockchain_height() const - // avg seconds per block - const int seconds_per_block = DIFFICULTY_TARGET_V2; - // Calculated blockchain height -- uint64_t approx_blockchain_height = fork_block + (time(NULL) - fork_time)/seconds_per_block; -+ uint64_t approx_blockchain_height = fork_block + ((t > 0 ? t : time(NULL)) - fork_time)/seconds_per_block; - // testnet and stagenet got some huge rollbacks, so the estimation is way off - static const uint64_t approximate_rolled_back_blocks = m_nettype == TESTNET ? 342100 : 30000; - if ((m_nettype == TESTNET || m_nettype == STAGENET) && approx_blockchain_height > approximate_rolled_back_blocks) -@@ -14862,6 +14927,21 @@ bool wallet2::parse_uri(const std::string &uri, std::string &address, std::strin +- uint64_t approx_blockchain_height = m_nettype == TESTNET ? 0 : (time(NULL) - 1522624244)/307; ++ uint64_t approx_blockchain_height = m_nettype == TESTNET ? 0 : ((t > 0 ? t : time(NULL)) - 1522624244)/307; + LOG_PRINT_L2("Calculated blockchain height: " << approx_blockchain_height); + return approx_blockchain_height; + } +@@ -15262,15 +15327,6 @@ bool wallet2::parse_uri(const std::string &uri, std::string &address, std::strin //---------------------------------------------------------------------------------------------------- uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, uint8_t day) { -+ std::tm date = { 0, 0, 0, 0, 0, 0, 0, 0 }; -+ date.tm_year = year - 1900; -+ date.tm_mon = month - 1; -+ date.tm_mday = day; -+ if (date.tm_mon < 0 || 11 < date.tm_mon || date.tm_mday < 1 || 31 < date.tm_mday) -+ { -+ throw std::runtime_error("month or day out of range"); -+ } +- uint32_t version; +- if (!check_connection(&version)) +- { +- throw std::runtime_error("failed to connect to daemon: " + get_daemon_address()); +- } +- if (version < MAKE_CORE_RPC_VERSION(1, 6)) +- { +- throw std::runtime_error("this function requires RPC version 1.6 or higher"); +- } + std::tm date = { 0, 0, 0, 0, 0, 0, 0, 0 }; + date.tm_year = year - 1900; + date.tm_mon = month - 1; +@@ -15279,7 +15335,23 @@ uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, ui + { + throw std::runtime_error("month or day out of range"); + } + -+ uint64_t timestamp_target = std::mktime(&date); + uint64_t timestamp_target = std::mktime(&date); + + return get_blockchain_height_by_timestamp(timestamp_target); +} + +uint64_t wallet2::get_blockchain_height_by_timestamp(uint64_t timestamp_target) { - uint32_t version; - if (!check_connection(&version)) - { -@@ -14871,15 +14951,7 @@ uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, ui - { - throw std::runtime_error("this function requires RPC version 1.6 or higher"); - } -- std::tm date = { 0, 0, 0, 0, 0, 0, 0, 0 }; -- date.tm_year = year - 1900; -- date.tm_mon = month - 1; -- date.tm_mday = day; -- if (date.tm_mon < 0 || 11 < date.tm_mon || date.tm_mday < 1 || 31 < date.tm_mday) -- { -- throw std::runtime_error("month or day out of range"); -- } -- uint64_t timestamp_target = std::mktime(&date); ++ uint32_t version; ++ if (!check_connection(&version)) ++ { ++ throw std::runtime_error("failed to connect to daemon: " + get_daemon_address()); ++ } ++ if (version < MAKE_CORE_RPC_VERSION(1, 6)) ++ { ++ throw std::runtime_error("this function requires RPC version 1.6 or higher"); ++ } + std::string err; uint64_t height_min = 0; uint64_t height_max = get_daemon_blockchain_height(err) - 1; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h -index 3144a8fd3..b540eff6b 100644 +index df34f9abf..db5c1feb3 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -72,6 +72,7 @@ @@ -1273,7 +1268,7 @@ index 3144a8fd3..b540eff6b 100644 /*! * \brief Checks if light wallet. A light wallet sends view key to a server where the blockchain is scanned. */ -@@ -1466,8 +1490,8 @@ private: +@@ -1469,8 +1493,8 @@ private: /*! * \brief Calculates the approximate blockchain height from current date/time. */ @@ -1284,7 +1279,7 @@ index 3144a8fd3..b540eff6b 100644 std::vector select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool allow_rct); std::vector select_available_outputs(const std::function &f); std::vector select_available_unmixable_outputs(); -@@ -1559,6 +1583,7 @@ private: +@@ -1563,6 +1587,7 @@ private: 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 &unknown_parameters, std::string &error); uint64_t get_blockchain_height_by_date(uint16_t year, uint8_t month, uint8_t day); // 1<=month<=12, 1<=day<=31 @@ -1292,7 +1287,7 @@ index 3144a8fd3..b540eff6b 100644 bool is_synced(); -@@ -1874,6 +1899,7 @@ private: +@@ -1900,6 +1925,7 @@ private: std::string seed_language; /*!< Language of the mnemonics (seed). */ bool is_old_file_format; /*!< Whether the wallet file is of an old file format */ bool m_watch_only; /*!< no spend key */ @@ -1300,3 +1295,6 @@ index 3144a8fd3..b540eff6b 100644 bool m_multisig; /*!< if > 1 spend secret key will not match spend public key */ uint32_t m_multisig_threshold; std::vector m_multisig_signers; +-- +2.44.0 + diff --git a/patches/wownero/0002-background-sync.patch b/patches/wownero/0003-wallet-background-sync-with-just-the-view-key.patch similarity index 88% rename from patches/wownero/0002-background-sync.patch rename to patches/wownero/0003-wallet-background-sync-with-just-the-view-key.patch index 47c2e27..95a8cfa 100644 --- a/patches/wownero/0002-background-sync.patch +++ b/patches/wownero/0003-wallet-background-sync-with-just-the-view-key.patch @@ -1,30 +1,53 @@ -From ef8f294db9ac2e2fb02212d87b94e2b516587ca1 Mon Sep 17 00:00:00 2001 -From: Czarek Nakamoto -Date: Tue, 26 Mar 2024 08:53:13 +0100 -Subject: [PATCH] background-sync +From 9d6099e9c47f7cbd12f4d6550d6fda520733c2c5 Mon Sep 17 00:00:00 2001 +From: j-berman +Date: Thu, 13 Oct 2022 18:33:33 -0700 +Subject: [PATCH 3/9] wallet: background sync with just the view key +- When background syncing, the wallet wipes the spend key +from memory and processes all new transactions. The wallet saves +all receives, spends, and "plausible" spends of receives the +wallet does not know key images for. +- When background sync disabled, the wallet processes all +background synced txs and then clears the background sync cache. +- Adding "plausible" spends to the background sync cache ensures +that the wallet does not need to query the daemon to see if any +received outputs were spent while background sync was enabled. +This would harm privacy especially for users of 3rd party daemons. +- To enable the feature in the CLI wallet, the user can set +background-sync to reuse-wallet-password or +custom-background-password and the wallet automatically syncs in +the background when the wallet locks, then processes all +background synced txs when the wallet is unlocked. +- The custom-background-password option enables the user to +open a distinct background wallet that only has a view key saved +and can be opened/closed/synced separately from the main wallet. +When the main wallet opens, it processes the background wallet's +cache. +- To enable the feature in the RPC wallet, there is a new +`/setup_background_sync` endpoint. +- HW, multsig and view-only wallets cannot background sync. --- - src/cryptonote_basic/account.cpp | 11 + - src/cryptonote_basic/account.h | 1 + - src/cryptonote_config.h | 5 +- - src/simplewallet/simplewallet.cpp | 205 +++- - src/simplewallet/simplewallet.h | 1 + - src/wallet/api/wallet.cpp | 213 ++++- - src/wallet/api/wallet.h | 12 + - src/wallet/api/wallet2_api.h | 43 + - src/wallet/wallet2.cpp | 948 ++++++++++++++++++- - src/wallet/wallet2.h | 142 ++- - src/wallet/wallet_errors.h | 39 + - src/wallet/wallet_rpc_server.cpp | 162 ++++ - src/wallet/wallet_rpc_server.h | 6 + - src/wallet/wallet_rpc_server_commands_defs.h | 64 ++ - src/wallet/wallet_rpc_server_error_codes.h | 2 + - tests/functional_tests/transfer.py | 401 +++++++- - tests/functional_tests/util_resources.py | 25 + - tests/functional_tests/wallet.py | 43 +- - tests/unit_tests/wipeable_string.cpp | 12 + - utils/python-rpc/framework/wallet.py | 35 + - 20 files changed, 2282 insertions(+), 88 deletions(-) + src/cryptonote_basic/account.cpp | 11 + + src/cryptonote_basic/account.h | 1 + + src/cryptonote_config.h | 2 + + src/simplewallet/simplewallet.cpp | 205 +++- + src/simplewallet/simplewallet.h | 1 + + src/wallet/api/wallet.cpp | 230 +++- + src/wallet/api/wallet.h | 12 + + src/wallet/api/wallet2_api.h | 41 + + src/wallet/wallet2.cpp | 1029 ++++++++++++++++-- + src/wallet/wallet2.h | 155 ++- + src/wallet/wallet_errors.h | 39 + + src/wallet/wallet_rpc_server.cpp | 162 +++ + src/wallet/wallet_rpc_server.h | 6 + + src/wallet/wallet_rpc_server_commands_defs.h | 64 ++ + src/wallet/wallet_rpc_server_error_codes.h | 2 + + tests/functional_tests/transfer.py | 400 ++++++- + tests/functional_tests/util_resources.py | 25 + + tests/functional_tests/wallet.py | 43 +- + tests/unit_tests/wipeable_string.cpp | 12 + + utils/python-rpc/framework/wallet.py | 42 + + 20 files changed, 2350 insertions(+), 132 deletions(-) diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp index 4931c3740..2d556f285 100644 @@ -61,20 +84,10 @@ index 0099ebfe7..1f76febce 100644 void encrypt_keys(const crypto::chacha_key &key) { m_keys.encrypt(key); } diff --git a/src/cryptonote_config.h b/src/cryptonote_config.h -index 1c1830ad4..ff2464272 100644 +index 1c1830ad4..a192bd64d 100644 --- a/src/cryptonote_config.h +++ b/src/cryptonote_config.h -@@ -245,7 +245,8 @@ namespace config - } }; // Bender's nightmare - std::string const GENESIS_TX = "013c01ff0001ffffffffff1f029b2e4c0281c0b02e7c53291a94d1d0cbff8883f8024f5142ee494ffbbd08807121012a1a936be5d91c01ee876e38c13fab0ee11cbe86011a2bf7740fb5ebd39d267d"; - uint32_t const GENESIS_NONCE = 70; -- -+ std::string const BACKGROUND_WALLET_SUFFIX = ".background"; -+ - // Hash domain separators - const char HASH_KEY_BULLETPROOF_EXPONENT[] = "bulletproof"; - const char HASH_KEY_BULLETPROOF_PLUS_EXPONENT[] = "bulletproof_plus"; -@@ -255,6 +256,8 @@ namespace config +@@ -255,6 +255,8 @@ namespace config const unsigned char HASH_KEY_ENCRYPTED_PAYMENT_ID = 0x8d; const unsigned char HASH_KEY_WALLET = 0x8c; const unsigned char HASH_KEY_WALLET_CACHE = 0x8d; @@ -84,7 +97,7 @@ index 1c1830ad4..ff2464272 100644 const unsigned char HASH_KEY_MEMORY = 'k'; const unsigned char HASH_KEY_MULTISIG[] = {'M', 'u', 'l', 't' , 'i', 's', 'i', 'g', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp -index b437092a4..754f088d6 100644 +index b437092a4..394201028 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -155,6 +155,17 @@ typedef cryptonote::simple_wallet sw; @@ -281,7 +294,16 @@ index b437092a4..754f088d6 100644 if (args.empty()) { PRINT_USAGE(USAGE_SCAN_TX); -@@ -3909,6 +4017,7 @@ bool simple_wallet::set_variable(const std::vector &args) +@@ -3489,6 +3597,8 @@ simple_wallet::simple_wallet() + " Ignore outputs of amount below this threshold when spending.\n " + "track-uses <1|0>\n " + " Whether to keep track of owned outputs uses.\n " ++ "background-sync \n " ++ " Set this to enable scanning in the background with just the view key while the wallet is locked.\n " + "setup-background-mining <1|0>\n " + " Whether to enable background mining. Set this to support the network and to get a chance to receive new WOW.\n " + "device-name \n " +@@ -3909,6 +4019,7 @@ bool simple_wallet::set_variable(const std::vector &args) success_msg_writer() << "ignore-outputs-above = " << cryptonote::print_money(m_wallet->ignore_outputs_above()); success_msg_writer() << "ignore-outputs-below = " << cryptonote::print_money(m_wallet->ignore_outputs_below()); success_msg_writer() << "track-uses = " << m_wallet->track_uses(); @@ -289,7 +311,7 @@ index b437092a4..754f088d6 100644 success_msg_writer() << "setup-background-mining = " << setup_background_mining_string; success_msg_writer() << "device-name = " << m_wallet->device_name(); success_msg_writer() << "export-format = " << (m_wallet->export_format() == tools::wallet2::ExportFormat::Ascii ? "ascii" : "binary"); -@@ -3928,6 +4037,7 @@ bool simple_wallet::set_variable(const std::vector &args) +@@ -3928,6 +4039,7 @@ bool simple_wallet::set_variable(const std::vector &args) } else { @@ -297,7 +319,7 @@ index b437092a4..754f088d6 100644 #define CHECK_SIMPLE_VARIABLE(name, f, help) do \ if (args[0] == name) { \ -@@ -3981,6 +4091,7 @@ bool simple_wallet::set_variable(const std::vector &args) +@@ -3981,6 +4093,7 @@ bool simple_wallet::set_variable(const std::vector &args) CHECK_SIMPLE_VARIABLE("ignore-outputs-above", set_ignore_outputs_above, tr("amount")); CHECK_SIMPLE_VARIABLE("ignore-outputs-below", set_ignore_outputs_below, tr("amount")); CHECK_SIMPLE_VARIABLE("track-uses", set_track_uses, tr("0 or 1")); @@ -305,7 +327,7 @@ index b437092a4..754f088d6 100644 CHECK_SIMPLE_VARIABLE("show-wallet-name-when-locked", set_show_wallet_name_when_locked, tr("1 or 0")); CHECK_SIMPLE_VARIABLE("show-detailed-prompt", set_show_detailed_prompt, tr("1 or 0")); CHECK_SIMPLE_VARIABLE("inactivity-lock-timeout", set_inactivity_lock_timeout, tr("unsigned integer (seconds, 0 to disable)")); -@@ -4936,7 +5047,10 @@ std::string simple_wallet::get_mnemonic_language() +@@ -4936,7 +5049,10 @@ std::string simple_wallet::get_mnemonic_language() //---------------------------------------------------------------------------------------------------- boost::optional simple_wallet::get_and_verify_password() const { @@ -317,7 +339,7 @@ index b437092a4..754f088d6 100644 if (!pwd_container) return boost::none; -@@ -5240,6 +5354,8 @@ boost::optional simple_wallet::open_wallet(const boost::p +@@ -5240,6 +5356,8 @@ boost::optional simple_wallet::open_wallet(const boost::p prefix = tr("Opened watch-only wallet"); else if (m_wallet->multisig(&ready, &threshold, &total)) prefix = (boost::format(tr("Opened %u/%u multisig wallet%s")) % threshold % total % (ready ? "" : " (not yet finalized)")).str(); @@ -326,7 +348,7 @@ index b437092a4..754f088d6 100644 else prefix = tr("Opened wallet"); message_writer(console_color_white, true) << -@@ -5447,6 +5563,10 @@ void simple_wallet::stop_background_mining() +@@ -5447,6 +5565,10 @@ void simple_wallet::stop_background_mining() //---------------------------------------------------------------------------------------------------- void simple_wallet::check_background_mining(const epee::wipeable_string &password) { @@ -337,7 +359,7 @@ index b437092a4..754f088d6 100644 tools::wallet2::BackgroundMiningSetupType setup = m_wallet->setup_background_mining(); if (setup == tools::wallet2::BackgroundMiningNo) { -@@ -6319,6 +6439,7 @@ bool simple_wallet::show_blockchain_height(const std::vector& args) +@@ -6319,6 +6441,7 @@ bool simple_wallet::show_blockchain_height(const std::vector& args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::rescan_spent(const std::vector &args) { @@ -345,7 +367,7 @@ index b437092a4..754f088d6 100644 if (!m_wallet->is_trusted_daemon()) { fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon"); -@@ -6616,11 +6737,28 @@ void simple_wallet::check_for_inactivity_lock(bool user) +@@ -6616,10 +6739,27 @@ void simple_wallet::check_for_inactivity_lock(bool user) " B B " << std::endl << "" << std::endl; } @@ -368,14 +390,13 @@ index b437092a4..754f088d6 100644 + ? tr("The background password is required to unlock the console.") + : tr("The wallet password is required to unlock the console.") + ); - ++ + if (m_wallet->is_background_syncing()) + tools::msg_writer() << tr("\nSyncing in the background while locked...") << std::endl; -+ + const bool show_wallet_name = m_wallet->show_wallet_name_when_locked(); if (show_wallet_name) - { -@@ -6632,8 +6770,16 @@ void simple_wallet::check_for_inactivity_lock(bool user) +@@ -6632,8 +6772,16 @@ void simple_wallet::check_for_inactivity_lock(bool user) } try { @@ -393,7 +414,7 @@ index b437092a4..754f088d6 100644 } catch (...) { /* do nothing, just let the loop loop */ } } -@@ -6660,6 +6806,7 @@ bool simple_wallet::on_command(bool (simple_wallet::*cmd)(const std::vector &args_, bool called_by_mms) { // "transfer [index=[,,...]] [] []
[]" @@ -401,7 +422,7 @@ index b437092a4..754f088d6 100644 if (!try_connect_to_daemon()) return false; -@@ -7133,6 +7280,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector &args_) { @@ -409,7 +430,7 @@ index b437092a4..754f088d6 100644 if (args_.size() < 1) { PRINT_USAGE(USAGE_TRANSFER); -@@ -7144,6 +7292,7 @@ bool simple_wallet::transfer(const std::vector &args_) +@@ -7144,6 +7294,7 @@ bool simple_wallet::transfer(const std::vector &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::locked_transfer(const std::vector &args_) { @@ -417,7 +438,7 @@ index b437092a4..754f088d6 100644 if (args_.size() < 1) { PRINT_USAGE(USAGE_LOCKED_TRANSFER); -@@ -7155,6 +7304,7 @@ bool simple_wallet::locked_transfer(const std::vector &args_) +@@ -7155,6 +7306,7 @@ bool simple_wallet::locked_transfer(const std::vector &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::locked_sweep_all(const std::vector &args_) { @@ -425,7 +446,7 @@ index b437092a4..754f088d6 100644 if (args_.size() < 1) { PRINT_USAGE(USAGE_LOCKED_SWEEP_ALL); -@@ -7167,6 +7317,7 @@ bool simple_wallet::locked_sweep_all(const std::vector &args_) +@@ -7167,6 +7319,7 @@ bool simple_wallet::locked_sweep_all(const std::vector &args_) bool simple_wallet::sweep_unmixable(const std::vector &args_) { @@ -433,7 +454,7 @@ index b437092a4..754f088d6 100644 if (!try_connect_to_daemon()) return true; -@@ -7274,6 +7425,7 @@ bool simple_wallet::sweep_unmixable(const std::vector &args_) +@@ -7274,6 +7427,7 @@ bool simple_wallet::sweep_unmixable(const std::vector &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, const std::vector &args_) { @@ -441,7 +462,7 @@ index b437092a4..754f088d6 100644 auto print_usage = [this, account, below]() { if (below) -@@ -7590,6 +7742,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co +@@ -7590,6 +7744,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co //---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_single(const std::vector &args_) { @@ -449,7 +470,7 @@ index b437092a4..754f088d6 100644 if (!try_connect_to_daemon()) return true; -@@ -7828,12 +7981,14 @@ bool simple_wallet::sweep_single(const std::vector &args_) +@@ -7828,12 +7983,14 @@ bool simple_wallet::sweep_single(const std::vector &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_all(const std::vector &args_) { @@ -464,7 +485,7 @@ index b437092a4..754f088d6 100644 auto local_args = args_; if (local_args.empty()) { -@@ -7854,6 +8009,7 @@ bool simple_wallet::sweep_account(const std::vector &args_) +@@ -7854,6 +8011,7 @@ bool simple_wallet::sweep_account(const std::vector &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_below(const std::vector &args_) { @@ -472,7 +493,7 @@ index b437092a4..754f088d6 100644 uint64_t below = 0; if (args_.size() < 1) { -@@ -7872,6 +8028,7 @@ bool simple_wallet::sweep_below(const std::vector &args_) +@@ -7872,6 +8030,7 @@ bool simple_wallet::sweep_below(const std::vector &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::donate(const std::vector &args_) { @@ -480,7 +501,7 @@ index b437092a4..754f088d6 100644 std::vector local_args = args_; if(local_args.empty() || local_args.size() > 5) { -@@ -7933,6 +8090,7 @@ bool simple_wallet::donate(const std::vector &args_) +@@ -7933,6 +8092,7 @@ bool simple_wallet::donate(const std::vector &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::accept_loaded_tx(const std::function get_num_txes, const std::function &get_tx, const std::string &extra_message) { @@ -488,17 +509,15 @@ index b437092a4..754f088d6 100644 // gather info to ask the user uint64_t amount = 0, amount_to_dests = 0, change = 0; size_t min_ring_size = ~0; -@@ -8113,7 +8271,8 @@ bool simple_wallet::sign_transfer(const std::vector &args_) +@@ -8113,6 +8273,7 @@ bool simple_wallet::sign_transfer(const std::vector &args_) fail_msg_writer() << tr("This is a watch only wallet"); return true; } -- + CHECK_IF_BACKGROUND_SYNCING("cannot sign transfer"); -+ + bool export_raw = false; std::string unsigned_filename = "unsigned_wownero_tx"; - if (args_.size() > 2 || (args_.size() == 2 && args_[0] != "export_raw")) -@@ -8220,6 +8379,8 @@ std::string get_tx_key_stream(crypto::secret_key tx_key, std::vector &args_) { @@ -507,7 +526,7 @@ index b437092a4..754f088d6 100644 std::vector local_args = args_; if (m_wallet->key_on_device() && m_wallet->get_account().get_device().get_type() != hw::device::TREZOR) -@@ -8260,6 +8421,8 @@ bool simple_wallet::get_tx_key(const std::vector &args_) +@@ -8260,6 +8423,8 @@ bool simple_wallet::get_tx_key(const std::vector &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::set_tx_key(const std::vector &args_) { @@ -516,7 +535,7 @@ index b437092a4..754f088d6 100644 std::vector local_args = args_; if(local_args.size() != 2 && local_args.size() != 3) { -@@ -8336,6 +8499,8 @@ bool simple_wallet::set_tx_key(const std::vector &args_) +@@ -8336,6 +8501,8 @@ bool simple_wallet::set_tx_key(const std::vector &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::get_tx_proof(const std::vector &args) { @@ -525,7 +544,7 @@ index b437092a4..754f088d6 100644 if (args.size() != 2 && args.size() != 3) { PRINT_USAGE(USAGE_GET_TX_PROOF); -@@ -8542,6 +8707,7 @@ bool simple_wallet::check_tx_proof(const std::vector &args) +@@ -8542,6 +8709,7 @@ bool simple_wallet::check_tx_proof(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::get_spend_proof(const std::vector &args) { @@ -533,7 +552,7 @@ index b437092a4..754f088d6 100644 if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); -@@ -8626,6 +8792,7 @@ bool simple_wallet::check_spend_proof(const std::vector &args) +@@ -8626,6 +8794,7 @@ bool simple_wallet::check_spend_proof(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::get_reserve_proof(const std::vector &args) { @@ -541,7 +560,7 @@ index b437092a4..754f088d6 100644 if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); -@@ -9312,6 +9479,8 @@ bool simple_wallet::unspent_outputs(const std::vector &args_) +@@ -9312,6 +9481,8 @@ bool simple_wallet::unspent_outputs(const std::vector &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::rescan_blockchain(const std::vector &args_) { @@ -550,7 +569,7 @@ index b437092a4..754f088d6 100644 uint64_t start_height = 0; ResetType reset_type = ResetSoft; -@@ -9622,6 +9791,7 @@ bool simple_wallet::account(const std::vector &args/* = std::vector +@@ -9622,6 +9793,7 @@ bool simple_wallet::account(const std::vector &args/* = std::vector if (command == "new") { // create a new account and switch to it @@ -558,7 +577,7 @@ index b437092a4..754f088d6 100644 std::string label = boost::join(local_args, " "); if (label.empty()) label = tr("(Untitled account)"); -@@ -9652,6 +9822,7 @@ bool simple_wallet::account(const std::vector &args/* = std::vector +@@ -9652,6 +9824,7 @@ bool simple_wallet::account(const std::vector &args/* = std::vector else if (command == "label" && local_args.size() >= 1) { // set label of the specified account @@ -566,7 +585,7 @@ index b437092a4..754f088d6 100644 uint32_t index_major; if (!epee::string_tools::get_xtype_from_string(index_major, local_args[0])) { -@@ -9673,6 +9844,7 @@ bool simple_wallet::account(const std::vector &args/* = std::vector +@@ -9673,6 +9846,7 @@ bool simple_wallet::account(const std::vector &args/* = std::vector } else if (command == "tag" && local_args.size() >= 2) { @@ -574,7 +593,7 @@ index b437092a4..754f088d6 100644 const std::string tag = local_args[0]; std::set account_indices; for (size_t i = 1; i < local_args.size(); ++i) -@@ -9697,6 +9869,7 @@ bool simple_wallet::account(const std::vector &args/* = std::vector +@@ -9697,6 +9871,7 @@ bool simple_wallet::account(const std::vector &args/* = std::vector } else if (command == "untag" && local_args.size() >= 1) { @@ -582,7 +601,7 @@ index b437092a4..754f088d6 100644 std::set account_indices; for (size_t i = 0; i < local_args.size(); ++i) { -@@ -9720,6 +9893,7 @@ bool simple_wallet::account(const std::vector &args/* = std::vector +@@ -9720,6 +9895,7 @@ bool simple_wallet::account(const std::vector &args/* = std::vector } else if (command == "tag_description" && local_args.size() >= 1) { @@ -590,7 +609,7 @@ index b437092a4..754f088d6 100644 const std::string tag = local_args[0]; std::string description; if (local_args.size() > 1) -@@ -9837,6 +10011,7 @@ bool simple_wallet::print_address(const std::vector &args/* = std:: +@@ -9837,6 +10013,7 @@ bool simple_wallet::print_address(const std::vector &args/* = std:: } else if (local_args[0] == "new") { @@ -598,7 +617,7 @@ index b437092a4..754f088d6 100644 local_args.erase(local_args.begin()); std::string label; if (local_args.size() > 0) -@@ -9849,6 +10024,7 @@ bool simple_wallet::print_address(const std::vector &args/* = std:: +@@ -9849,6 +10026,7 @@ bool simple_wallet::print_address(const std::vector &args/* = std:: } else if (local_args[0] == "mnew") { @@ -606,7 +625,7 @@ index b437092a4..754f088d6 100644 local_args.erase(local_args.begin()); if (local_args.size() != 1) { -@@ -9874,6 +10050,7 @@ bool simple_wallet::print_address(const std::vector &args/* = std:: +@@ -9874,6 +10052,7 @@ bool simple_wallet::print_address(const std::vector &args/* = std:: } else if (local_args[0] == "one-off") { @@ -614,7 +633,7 @@ index b437092a4..754f088d6 100644 local_args.erase(local_args.begin()); std::string label; if (local_args.size() != 2) -@@ -9892,6 +10069,7 @@ bool simple_wallet::print_address(const std::vector &args/* = std:: +@@ -9892,6 +10071,7 @@ bool simple_wallet::print_address(const std::vector &args/* = std:: } else if (local_args.size() >= 2 && local_args[0] == "label") { @@ -622,7 +641,7 @@ index b437092a4..754f088d6 100644 if (!epee::string_tools::get_xtype_from_string(index, local_args[1])) { fail_msg_writer() << tr("failed to parse index: ") << local_args[1]; -@@ -10038,6 +10216,8 @@ bool simple_wallet::print_integrated_address(const std::vector &arg +@@ -10038,6 +10218,8 @@ bool simple_wallet::print_integrated_address(const std::vector &arg //---------------------------------------------------------------------------------------------------- bool simple_wallet::address_book(const std::vector &args/* = std::vector()*/) { @@ -631,7 +650,7 @@ index b437092a4..754f088d6 100644 if (args.size() == 0) { } -@@ -10098,6 +10278,8 @@ bool simple_wallet::address_book(const std::vector &args/* = std::v +@@ -10098,6 +10280,8 @@ bool simple_wallet::address_book(const std::vector &args/* = std::v //---------------------------------------------------------------------------------------------------- bool simple_wallet::set_tx_note(const std::vector &args) { @@ -640,7 +659,7 @@ index b437092a4..754f088d6 100644 if (args.size() == 0) { PRINT_USAGE(USAGE_SET_TX_NOTE); -@@ -10126,6 +10308,8 @@ bool simple_wallet::set_tx_note(const std::vector &args) +@@ -10126,6 +10310,8 @@ bool simple_wallet::set_tx_note(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::get_tx_note(const std::vector &args) { @@ -649,7 +668,7 @@ index b437092a4..754f088d6 100644 if (args.size() != 1) { PRINT_USAGE(USAGE_GET_TX_NOTE); -@@ -10151,6 +10335,8 @@ bool simple_wallet::get_tx_note(const std::vector &args) +@@ -10151,6 +10337,8 @@ bool simple_wallet::get_tx_note(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::set_description(const std::vector &args) { @@ -658,7 +677,7 @@ index b437092a4..754f088d6 100644 // 0 arguments allowed, for setting the description to empty string std::string description = ""; -@@ -10167,6 +10353,8 @@ bool simple_wallet::set_description(const std::vector &args) +@@ -10167,6 +10355,8 @@ bool simple_wallet::set_description(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::get_description(const std::vector &args) { @@ -667,7 +686,7 @@ index b437092a4..754f088d6 100644 if (args.size() != 0) { PRINT_USAGE(USAGE_GET_DESCRIPTION); -@@ -10225,6 +10413,8 @@ bool simple_wallet::wallet_info(const std::vector &args) +@@ -10225,6 +10415,8 @@ bool simple_wallet::wallet_info(const std::vector &args) type = tr("Watch only"); else if (m_wallet->multisig(&ready, &threshold, &total)) type = (boost::format(tr("%u/%u multisig%s")) % threshold % total % (ready ? "" : " (not yet finalized)")).str(); @@ -676,7 +695,7 @@ index b437092a4..754f088d6 100644 else type = tr("Normal"); message_writer() << tr("Type: ") << type; -@@ -10236,6 +10426,7 @@ bool simple_wallet::wallet_info(const std::vector &args) +@@ -10236,6 +10428,7 @@ bool simple_wallet::wallet_info(const std::vector &args) //---------------------------------------------------------------------------------------------------- bool simple_wallet::sign(const std::vector &args) { @@ -684,7 +703,7 @@ index b437092a4..754f088d6 100644 if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); -@@ -10343,6 +10534,7 @@ bool simple_wallet::export_key_images(const std::vector &args_) +@@ -10343,6 +10536,7 @@ bool simple_wallet::export_key_images(const std::vector &args_) fail_msg_writer() << tr("command not supported by HW wallet"); return true; } @@ -692,7 +711,7 @@ index b437092a4..754f088d6 100644 auto args = args_; if (m_wallet->watch_only()) -@@ -10396,6 +10588,7 @@ bool simple_wallet::import_key_images(const std::vector &args) +@@ -10396,6 +10590,7 @@ bool simple_wallet::import_key_images(const std::vector &args) fail_msg_writer() << tr("command not supported by HW wallet"); return true; } @@ -700,7 +719,7 @@ index b437092a4..754f088d6 100644 if (!m_wallet->is_trusted_daemon()) { fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon"); -@@ -10504,6 +10697,7 @@ bool simple_wallet::export_outputs(const std::vector &args_) +@@ -10504,6 +10699,7 @@ bool simple_wallet::export_outputs(const std::vector &args_) fail_msg_writer() << tr("command not supported by HW wallet"); return true; } @@ -708,7 +727,7 @@ index b437092a4..754f088d6 100644 auto args = args_; bool all = false; -@@ -10553,6 +10747,7 @@ bool simple_wallet::import_outputs(const std::vector &args) +@@ -10553,6 +10749,7 @@ bool simple_wallet::import_outputs(const std::vector &args) fail_msg_writer() << tr("command not supported by HW wallet"); return true; } @@ -729,7 +748,7 @@ index 8e3477ba3..ae1aa312b 100644 bool set_show_detailed_prompt(const std::vector &args = std::vector()); bool set_inactivity_lock_timeout(const std::vector &args = std::vector()); diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp -index db9c2b5d9..1f3bf4ab7 100644 +index db9c2b5d9..5ef3132d2 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -56,6 +56,40 @@ using namespace cryptonote; @@ -1148,18 +1167,35 @@ index db9c2b5d9..1f3bf4ab7 100644 void WalletImpl::clearStatus() const { boost::lock_guard l(m_statusMutex); -@@ -2673,9 +2860,7 @@ void WalletImpl::doRefresh() - if(rescan) - m_wallet->rescan_blockchain(false); - m_wallet->refresh(true); +@@ -2670,11 +2857,22 @@ void WalletImpl::doRefresh() + boost::lock_guard guarg(m_refreshMutex2); + do try { + LOG_PRINT_L3(__FUNCTION__ << ": doRefresh, rescan = "<rescan_blockchain(false); +- m_wallet->refresh(true); - if (!m_synchronized) { - m_synchronized = true; -- } -+ m_synchronized = m_wallet->is_synced(); ++ // 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()) { ++ if(rescan) ++ m_wallet->rescan_blockchain(false); ++ m_wallet->refresh(trustedDaemon()); ++ m_synchronized = m_wallet->is_synced(); ++ // assuming if we have empty history, it wasn't initialized yet ++ // for further history changes client need to update history in ++ // "on_money_received" and "on_money_sent" callbacks ++ if (m_history->count() == 0) { ++ m_history->refresh(); ++ } ++ m_wallet->find_and_save_rings(false); ++ } else { ++ LOG_PRINT_L3(__FUNCTION__ << ": skipping refresh - daemon is not synced"); + } // assuming if we have empty history, it wasn't initialized yet // for further history changes client need to update history in - // "on_money_received" and "on_money_sent" callbacks -@@ -2784,6 +2969,24 @@ bool WalletImpl::doInit(const string &daemon_address, const std::string &proxy_a +@@ -2784,6 +2982,24 @@ bool WalletImpl::doInit(const string &daemon_address, const std::string &proxy_a return true; } @@ -1184,7 +1220,7 @@ index db9c2b5d9..1f3bf4ab7 100644 bool WalletImpl::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 &unknown_parameters, std::string &error) { return m_wallet->parse_uri(uri, address, payment_id, amount, tx_description, recipient_name, unknown_parameters, error); -@@ -2802,6 +3005,8 @@ std::string WalletImpl::getDefaultDataDir() const +@@ -2802,6 +3018,8 @@ std::string WalletImpl::getDefaultDataDir() const bool WalletImpl::rescanSpent() { clearStatus(); @@ -1194,12 +1230,12 @@ index db9c2b5d9..1f3bf4ab7 100644 setStatusError(tr("Rescan spent can only be used with a trusted daemon")); return false; diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h -index 28135c82a..35c05ef5b 100644 +index 28135c82a..fc6341861 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h -@@ -198,6 +198,13 @@ public: - bool importTransaction(const std::string &txid, std::vector &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen) override; - bool scanTransactions(const std::vector &txids) override; +@@ -216,6 +216,13 @@ public: + virtual std::string printAddressBook() override; + virtual std::string printScannedPoolTxs() override; + bool setupBackgroundSync(const BackgroundSyncType background_sync_type, const std::string &wallet_password, const optional &background_cache_password = optional()) override; + BackgroundSyncType getBackgroundSyncType() const override; @@ -1208,9 +1244,9 @@ index 28135c82a..35c05ef5b 100644 + bool isBackgroundSyncing() const override; + bool isBackgroundWallet() const override; + - virtual std::string printBlockchain() override; - virtual std::string printTransfers() override; - virtual std::string printPayments() override; + virtual void disposeTransaction(PendingTransaction * t) override; + virtual uint64_t estimateTransactionFee(const std::vector> &destinations, + PendingTransaction::Priority priority) const override; @@ -285,6 +292,7 @@ private: bool isNewWallet() const; void pendingTxPostProcess(PendingTransactionImpl * pending); @@ -1231,7 +1267,7 @@ index 28135c82a..35c05ef5b 100644 std::unique_ptr m_history; std::unique_ptr m_wallet2Callback; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h -index a0ed60a39..648dc29b5 100644 +index a0ed60a39..626c63fc5 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h @@ -544,6 +544,12 @@ struct Wallet @@ -1247,10 +1283,10 @@ index a0ed60a39..648dc29b5 100644 virtual ~Wallet() = 0; virtual std::string seed(const std::string& seed_offset = "") const = 0; virtual std::string getSeedLanguage() const = 0; -@@ -1075,6 +1081,43 @@ struct Wallet - */ - virtual bool scanTransactions(const std::vector &txids) = 0; +@@ -1094,6 +1100,41 @@ struct Wallet + virtual std::string printScannedPoolTxs() = 0; + virtual bool importTransaction(const std::string &txid, std::vector &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen) = 0; + /*! + * \brief setupBackgroundSync - setup background sync mode with just a view key + * \param background_sync_type - the mode the wallet background syncs in @@ -1286,16 +1322,23 @@ index a0ed60a39..648dc29b5 100644 + * @brief isBackgroundWallet - returns true if the wallet is a background wallet + */ + virtual bool isBackgroundWallet() const = 0; -+ -+ - virtual std::string printBlockchain() = 0; - virtual std::string printTransfers() = 0; - virtual std::string printPayments() = 0; + + virtual TransactionHistory * history() = 0; + virtual AddressBook * addressBook() = 0; diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp -index 83aba6253..56b76c5f9 100644 +index 83aba6253..d7e2a9699 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp -@@ -1021,14 +1021,14 @@ uint64_t num_priv_multisig_keys_post_setup(uint64_t threshold, uint64_t total) +@@ -158,6 +158,8 @@ static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1"; + + static const std::string ASCII_OUTPUT_MAGIC = "WowneroAsciiDataV1"; + ++static const std::string BACKGROUND_WALLET_SUFFIX = ".background"; ++ + boost::mutex tools::wallet2::default_daemon_address_lock; + std::string tools::wallet2::default_daemon_address = ""; + +@@ -1021,14 +1023,14 @@ uint64_t num_priv_multisig_keys_post_setup(uint64_t threshold, uint64_t total) * @param keys_data_key the chacha key that encrypts wallet keys files * @return crypto::chacha_key the chacha key that encrypts the wallet cache files */ @@ -1312,7 +1355,7 @@ index 83aba6253..56b76c5f9 100644 cn_fast_hash(cache_key_data.data(), HASH_SIZE+1, (crypto::hash&) cache_key); return cache_key; -@@ -1116,7 +1116,7 @@ wallet_keys_unlocker::wallet_keys_unlocker(wallet2 &w, const boost::optional lock(lockers_lock); if (lockers++ > 0) locked = false; @@ -1321,19 +1364,19 @@ index 83aba6253..56b76c5f9 100644 { locked = false; return; -@@ -1233,6 +1233,11 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std - m_ignore_outputs_above(MONEY_SUPPLY), - m_ignore_outputs_below(0), +@@ -1235,6 +1237,11 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std m_track_uses(false), + m_show_wallet_name_when_locked(true), + m_show_detailed_prompt(true), + m_is_background_wallet(false), + m_background_sync_type(BackgroundSyncOff), + m_background_syncing(false), + m_processing_background_cache(false), + m_custom_background_key(boost::none), - m_show_wallet_name_when_locked(true), - m_show_detailed_prompt(true), m_inactivity_lock_timeout(DEFAULT_INACTIVITY_LOCK_TIMEOUT), -@@ -1897,6 +1902,9 @@ bool has_nonrequested_tx_at_height_or_above_requested(uint64_t height, const std + m_setup_background_mining(BackgroundMiningNo), + m_persistent_rpc_client_id(false), +@@ -1897,6 +1904,9 @@ bool has_nonrequested_tx_at_height_or_above_requested(uint64_t height, const std //---------------------------------------------------------------------------------------------------- void wallet2::scan_tx(const std::unordered_set &txids) { @@ -1343,7 +1386,7 @@ index 83aba6253..56b76c5f9 100644 // Get the transactions from daemon in batches sorted lowest height to highest tx_entry_data txs_to_scan = get_tx_entries(txids); if (txs_to_scan.tx_entries.empty()) -@@ -2206,11 +2214,11 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons +@@ -2206,11 +2216,11 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons THROW_WALLET_EXCEPTION_IF(i >= tx.vout.size(), error::wallet_internal_error, "Invalid vout index"); // if keys are encrypted, ask for password @@ -1357,7 +1400,7 @@ index 83aba6253..56b76c5f9 100644 { boost::optional pwd = m_callback->on_get_password(pool ? "output found in pool" : "output received"); THROW_WALLET_EXCEPTION_IF(!pwd, error::password_needed, tr("Password is needed to compute key image for incoming wownero")); -@@ -2222,7 +2230,7 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons +@@ -2222,7 +2232,7 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons crypto::public_key output_public_key; THROW_WALLET_EXCEPTION_IF(!get_output_public_key(tx.vout[i], output_public_key), error::wallet_internal_error, "Failed to get output public key"); @@ -1366,7 +1409,7 @@ index 83aba6253..56b76c5f9 100644 { tx_scan_info.in_ephemeral.pub = output_public_key; tx_scan_info.in_ephemeral.sec = crypto::null_skey; -@@ -2479,6 +2487,14 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote +@@ -2479,6 +2489,22 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote THROW_WALLET_EXCEPTION_IF(tx.vout.size() != o_indices.size(), error::wallet_internal_error, "transactions outputs size=" + std::to_string(tx.vout.size()) + " not match with daemon response size=" + std::to_string(o_indices.size())); @@ -1375,13 +1418,21 @@ index 83aba6253..56b76c5f9 100644 + if (m_background_syncing && m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end()) + { + size_t bgs_idx = m_background_sync_data.txs.size(); ++ background_synced_tx_t bgs_tx = { ++ .index_in_background_sync_data = bgs_idx, ++ .tx = tx, ++ .output_indices = o_indices, ++ .height = height, ++ .block_timestamp = ts, ++ .double_spend_seen = double_spend_seen ++ }; + LOG_PRINT_L2("Adding received tx " << txid << " to background sync data (idx=" << bgs_idx << ")"); -+ m_background_sync_data.txs.insert({txid, background_synced_tx{bgs_idx, tx, o_indices, height, ts, double_spend_seen}}); ++ m_background_sync_data.txs.insert({txid, std::move(bgs_tx)}); + } } for(size_t o: outs) -@@ -2505,7 +2521,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote +@@ -2505,7 +2531,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote td.m_tx = (const cryptonote::transaction_prefix&)tx; td.m_txid = txid; td.m_key_image = tx_scan_info[o].ki; @@ -1390,7 +1441,7 @@ index 83aba6253..56b76c5f9 100644 if (!td.m_key_image_known) { // we might have cold signed, and have a mapping to key images -@@ -2696,10 +2712,17 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote +@@ -2696,10 +2722,25 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote set_spent(it->second, height); if (!ignore_callbacks && 0 != m_callback) m_callback->on_money_spent(height, txid, tx, amount, tx, td.m_subaddr_index); @@ -1398,8 +1449,16 @@ index 83aba6253..56b76c5f9 100644 + if (m_background_syncing && m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end()) + { + size_t bgs_idx = m_background_sync_data.txs.size(); ++ background_synced_tx_t bgs_tx = { ++ .index_in_background_sync_data = bgs_idx, ++ .tx = tx, ++ .output_indices = o_indices, ++ .height = height, ++ .block_timestamp = ts, ++ .double_spend_seen = double_spend_seen ++ }; + LOG_PRINT_L2("Adding spent tx " << txid << " to background sync data (idx=" << bgs_idx << ")"); -+ m_background_sync_data.txs.insert({txid, background_synced_tx{bgs_idx, tx, o_indices, height, ts, double_spend_seen}}); ++ m_background_sync_data.txs.insert({txid, std::move(bgs_tx)}); + } } } @@ -1409,7 +1468,7 @@ index 83aba6253..56b76c5f9 100644 { PERF_TIMER(track_uses); const uint64_t amount = in_to_key.amount; -@@ -2713,7 +2736,19 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote +@@ -2713,7 +2754,27 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote { size_t idx = i->second; THROW_WALLET_EXCEPTION_IF(idx >= m_transfers.size(), error::wallet_internal_error, "Output tracker cache index out of range"); @@ -1424,13 +1483,21 @@ index 83aba6253..56b76c5f9 100644 + if (m_background_syncing && !m_transfers[idx].m_key_image_known && m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end()) + { + size_t bgs_idx = m_background_sync_data.txs.size(); ++ background_synced_tx_t bgs_tx = { ++ .index_in_background_sync_data = bgs_idx, ++ .tx = tx, ++ .output_indices = o_indices, ++ .height = height, ++ .block_timestamp = ts, ++ .double_spend_seen = double_spend_seen ++ }; + LOG_PRINT_L2("Adding plausible spent tx " << txid << " to background sync data (idx=" << bgs_idx << ")"); -+ m_background_sync_data.txs.insert({txid, background_synced_tx{bgs_idx, tx, o_indices, height, ts, double_spend_seen}}); ++ m_background_sync_data.txs.insert({txid, std::move(bgs_tx)}); + } } } } -@@ -2723,7 +2758,16 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote +@@ -2723,7 +2784,24 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote continue; for (uint64_t offset: offsets) if (offset == td.m_global_output_index) @@ -1441,14 +1508,22 @@ index 83aba6253..56b76c5f9 100644 + if (m_background_syncing && !td.m_key_image_known && m_background_sync_data.txs.find(txid) == m_background_sync_data.txs.end()) + { + size_t bgs_idx = m_background_sync_data.txs.size(); ++ background_synced_tx_t bgs_tx = { ++ .index_in_background_sync_data = bgs_idx, ++ .tx = tx, ++ .output_indices = o_indices, ++ .height = height, ++ .block_timestamp = ts, ++ .double_spend_seen = double_spend_seen ++ }; + LOG_PRINT_L2("Adding plausible spent tx " << txid << " to background sync data (idx=" << bgs_idx << ")"); -+ m_background_sync_data.txs.insert({txid, background_synced_tx{bgs_idx, tx, o_indices, height, ts, double_spend_seen}}); ++ m_background_sync_data.txs.insert({txid, std::move(bgs_tx)}); + } + } } } } -@@ -3096,8 +3140,8 @@ void wallet2::pull_blocks(bool first, bool try_incremental, uint64_t start_heigh +@@ -3096,8 +3174,8 @@ void wallet2::pull_blocks(bool first, bool try_incremental, uint64_t start_heigh req.start_height = start_height; req.no_miner_tx = m_refresh_type == RefreshNoCoinbase; @@ -1459,7 +1534,7 @@ index 83aba6253..56b76c5f9 100644 req.pool_info_since = m_pool_info_query_time; { -@@ -3124,7 +3168,7 @@ void wallet2::pull_blocks(bool first, bool try_incremental, uint64_t start_heigh +@@ -3124,7 +3202,7 @@ void wallet2::pull_blocks(bool first, bool try_incremental, uint64_t start_heigh << ", height " << blocks_start_height + blocks.size() << ", node height " << res.current_height << ", pool info " << static_cast(res.pool_info_extent)); @@ -1468,7 +1543,7 @@ index 83aba6253..56b76c5f9 100644 { if (res.pool_info_extent != COMMAND_RPC_GET_BLOCKS_FAST::NONE) { -@@ -3636,6 +3680,9 @@ void wallet2::process_unconfirmed_transfer(bool incremental, const crypto::hash +@@ -3636,6 +3714,9 @@ void wallet2::process_unconfirmed_transfer(bool incremental, const crypto::hash // incremental update anymore, because with that we might miss some txs altogether. void wallet2::update_pool_state(std::vector> &process_txs, bool refreshed, bool try_incremental) { @@ -1478,7 +1553,7 @@ index 83aba6253..56b76c5f9 100644 bool updated = false; if (m_pool_info_query_time != 0 && try_incremental) { -@@ -4262,6 +4309,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo +@@ -4262,6 +4343,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo } m_first_refresh_done = true; @@ -1487,7 +1562,7 @@ index 83aba6253..56b76c5f9 100644 LOG_PRINT_L1("Refresh done, blocks received: " << blocks_fetched << ", balance (all accounts): " << print_money(balance_all(false)) << ", unlocked: " << print_money(unlocked_balance_all(false))); } -@@ -4347,6 +4396,14 @@ wallet2::detached_blockchain_data wallet2::detach_blockchain(uint64_t height, st +@@ -4347,6 +4430,14 @@ wallet2::detached_blockchain_data wallet2::detach_blockchain(uint64_t height, st td.m_uses.pop_back(); } @@ -1502,8 +1577,11 @@ index 83aba6253..56b76c5f9 100644 if (output_tracker_cache) output_tracker_cache->clear(); -@@ -4423,6 +4480,9 @@ void wallet2::handle_reorg(uint64_t height, std::map m_blockchain.offset(), error::wallet_internal_error, "Daemon claims reorg below last checkpoint"); ++ detached_blockchain_data dbd = detach_blockchain(height, output_tracker_cache); + if (m_background_syncing && height < m_background_sync_data.start_height) @@ -1512,7 +1590,7 @@ index 83aba6253..56b76c5f9 100644 if (m_callback) m_callback->on_reorg(height, dbd.detached_blockchain.size(), dbd.detached_tx_hashes.size()); } -@@ -4432,6 +4492,7 @@ bool wallet2::deinit() +@@ -4432,6 +4527,7 @@ bool wallet2::deinit() if(m_is_initialized) { m_is_initialized = false; unlock_keys_file(); @@ -1520,23 +1598,19 @@ index 83aba6253..56b76c5f9 100644 m_account.deinit(); } return true; -@@ -4458,6 +4519,9 @@ bool wallet2::clear() +@@ -4458,6 +4554,7 @@ bool wallet2::clear() m_device_last_key_image_sync = 0; m_pool_info_query_time = 0; m_skip_to_height = 0; -+ m_background_sync_data.first_refresh_done = false; -+ m_background_sync_data.start_height = 0; -+ m_background_sync_data.txs.clear(); ++ m_background_sync_data = background_sync_data_t{}; return true; } //---------------------------------------------------------------------------------------------------- -@@ -4476,13 +4540,32 @@ void wallet2::clear_soft(bool keep_key_images) +@@ -4476,13 +4573,30 @@ void wallet2::clear_soft(bool keep_key_images) m_scanned_pool_txs[1].clear(); m_pool_info_query_time = 0; m_skip_to_height = 0; -+ m_background_sync_data.first_refresh_done = false; -+ m_background_sync_data.start_height = 0; -+ m_background_sync_data.txs.clear(); ++ m_background_sync_data = background_sync_data_t{}; cryptonote::block b; generate_genesis(b); @@ -1564,7 +1638,7 @@ index 83aba6253..56b76c5f9 100644 /*! * \brief Stores wallet information to wallet file. * \param keys_file_name Name of wallet file -@@ -4494,16 +4577,35 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable +@@ -4494,16 +4608,35 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable { boost::optional keys_file_data = get_keys_file_data(password, watch_only); CHECK_AND_ASSERT_MES(keys_file_data != boost::none, false, "failed to generate wallet keys data"); @@ -1604,7 +1678,7 @@ index 83aba6253..56b76c5f9 100644 if (e) { boost::filesystem::remove(tmp_file_name); -@@ -4515,26 +4617,27 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable +@@ -4515,26 +4648,27 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable } //---------------------------------------------------------------------------------------------------- boost::optional wallet2::get_keys_file_data(const epee::wipeable_string& password, bool watch_only) @@ -1640,7 +1714,7 @@ index 83aba6253..56b76c5f9 100644 account.forget_spend_key(); account.encrypt_keys(key); -@@ -4669,6 +4772,9 @@ boost::optional wallet2::get_keys_file_data(const epee: +@@ -4669,6 +4803,9 @@ boost::optional wallet2::get_keys_file_data(const epee: value2.SetInt(m_track_uses ? 1 : 0); json.AddMember("track_uses", value2, json.GetAllocator()); @@ -1650,21 +1724,19 @@ index 83aba6253..56b76c5f9 100644 value2.SetInt(m_show_wallet_name_when_locked ? 1 : 0); json.AddMember("show_wallet_name_when_locked", value2, json.GetAllocator()); -@@ -4729,6 +4835,13 @@ boost::optional wallet2::get_keys_file_data(const epee: - value2.SetInt(m_enable_multisig ? 1 : 0); - json.AddMember("enable_multisig", value2, json.GetAllocator()); +@@ -4731,6 +4868,11 @@ boost::optional wallet2::get_keys_file_data(const epee: + value2.SetInt(m_polyseed ? 1 : 0); + json.AddMember("polyseed", value2, json.GetAllocator()); + if (m_background_sync_type == BackgroundSyncCustomPassword && !background_keys_file && m_custom_background_key) + { + value.SetString(reinterpret_cast(m_custom_background_key.get().data()), m_custom_background_key.get().size()); + json.AddMember("custom_background_key", value, json.GetAllocator()); + } -+ -+ - value2.SetInt(m_polyseed ? 1 : 0); - json.AddMember("polyseed", value2, json.GetAllocator()); -@@ -4758,13 +4871,81 @@ void wallet2::setup_keys(const epee::wipeable_string &password) + // Serialize the JSON object + rapidjson::StringBuffer buffer; +@@ -4758,13 +4900,81 @@ void wallet2::setup_keys(const epee::wipeable_string &password) m_account.decrypt_viewkey(key); } @@ -1747,7 +1819,7 @@ index 83aba6253..56b76c5f9 100644 if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only) decrypt_keys(original_password); setup_keys(new_password); -@@ -4823,8 +5004,24 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st +@@ -4823,8 +5033,24 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st std::string account_data; account_data.resize(keys_file_data.account_data.size()); crypto::chacha20(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); @@ -1773,26 +1845,26 @@ index 83aba6253..56b76c5f9 100644 // The contents should be JSON if the wallet follows the new format. if (json.Parse(account_data.c_str()).HasParseError()) { -@@ -4862,6 +5059,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st - m_ignore_outputs_above = MONEY_SUPPLY; - m_ignore_outputs_below = 0; +@@ -4864,6 +5090,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_track_uses = false; -+ m_background_sync_type = BackgroundSyncOff; m_show_wallet_name_when_locked = true; m_show_detailed_prompt = true; ++ m_background_sync_type = BackgroundSyncOff; m_inactivity_lock_timeout = DEFAULT_INACTIVITY_LOCK_TIMEOUT; -@@ -4880,6 +5078,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st - m_credits_target = 0; + m_setup_background_mining = BackgroundMiningNo; + m_subaddress_lookahead_major = SUBADDRESS_LOOKAHEAD_MAJOR; +@@ -4881,6 +5108,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_enable_multisig = false; m_allow_mismatched_daemon_version = true; -+ m_custom_background_key = boost::none; m_polyseed = false; ++ m_custom_background_key = boost::none; } else if(json.IsObject()) -@@ -5120,6 +5319,40 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st - GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, enable_multisig, int, Int, false, false); + { +@@ -5121,6 +5349,39 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st m_enable_multisig = field_enable_multisig; GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, polyseed, int, Int, false, false); + m_polyseed = field_polyseed; + + GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, background_sync_type, BackgroundSyncType, Int, false, BackgroundSyncOff); + m_background_sync_type = field_background_sync_type; @@ -1826,11 +1898,10 @@ index 83aba6253..56b76c5f9 100644 + { + LOG_ERROR("Unexpected field custom_background_key found in JSON"); + } -+ - m_polyseed = field_polyseed; } else -@@ -5184,12 +5417,17 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st + { +@@ -5184,12 +5445,17 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st const cryptonote::account_keys& keys = m_account.get_keys(); hw::device &hwdev = m_account.get_device(); r = r && hwdev.verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key); @@ -1850,7 +1921,7 @@ index 83aba6253..56b76c5f9 100644 return true; } -@@ -5204,11 +5442,12 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st +@@ -5204,11 +5470,12 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st * can be used prior to rewriting wallet keys file, to ensure user has entered the correct password * */ @@ -1865,7 +1936,7 @@ index 83aba6253..56b76c5f9 100644 lock_keys_file(); return r; } -@@ -5226,7 +5465,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password) +@@ -5226,7 +5493,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password) * can be used prior to rewriting wallet keys file, to ensure user has entered the correct password * */ @@ -1874,7 +1945,7 @@ index 83aba6253..56b76c5f9 100644 { rapidjson::Document json; wallet2::keys_file_data keys_file_data; -@@ -5243,9 +5482,22 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip +@@ -5243,9 +5510,22 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip std::string account_data; account_data.resize(keys_file_data.account_data.size()); crypto::chacha20(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); @@ -1898,7 +1969,7 @@ index 83aba6253..56b76c5f9 100644 // The contents should be JSON if the wallet follows the new format. if (json.Parse(account_data.c_str()).HasParseError()) { -@@ -5270,6 +5522,7 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip +@@ -5270,6 +5550,7 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip r = r && hwdev.verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key); if(!no_spend_key) r = r && hwdev.verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spend_public_key); @@ -1906,7 +1977,7 @@ index 83aba6253..56b76c5f9 100644 return r; } -@@ -5281,9 +5534,7 @@ void wallet2::encrypt_keys(const crypto::chacha_key &key) +@@ -5281,9 +5562,7 @@ void wallet2::encrypt_keys(const crypto::chacha_key &key) void wallet2::decrypt_keys(const crypto::chacha_key &key) { @@ -1917,7 +1988,7 @@ index 83aba6253..56b76c5f9 100644 m_account.encrypt_viewkey(key); m_account.decrypt_keys(key); -@@ -6001,11 +6252,30 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin +@@ -6001,11 +6280,30 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin { if (wallet_name.empty()) return; @@ -1948,13 +2019,13 @@ index 83aba6253..56b76c5f9 100644 } /*! * \brief Writes to a file named based on the normal wallet (doesn't generate key, assumes it's already there) -@@ -6348,6 +6618,16 @@ bool wallet2::wallet_valid_path_format(const std::string& file_path) +@@ -6348,6 +6646,16 @@ bool wallet2::wallet_valid_path_format(const std::string& file_path) return !file_path.empty(); } //---------------------------------------------------------------------------------------------------- +std::string wallet2::make_background_wallet_file_name(const std::string &wallet_file) +{ -+ return wallet_file + config::BACKGROUND_WALLET_SUFFIX; ++ return wallet_file + BACKGROUND_WALLET_SUFFIX; +} +//---------------------------------------------------------------------------------------------------- +std::string wallet2::make_background_keys_file_name(const std::string &wallet_file) @@ -1965,7 +2036,7 @@ index 83aba6253..56b76c5f9 100644 bool wallet2::parse_long_payment_id(const std::string& payment_id_str, crypto::hash& payment_id) { cryptonote::blobdata payment_id_data; -@@ -6583,10 +6863,135 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass +@@ -6583,10 +6891,81 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass THROW_WALLET_EXCEPTION_IF(true, error::file_read_error, "failed to load keys from buffer"); } @@ -1979,6 +2050,20 @@ index 83aba6253..56b76c5f9 100644 + if (!m_persistent_rpc_client_id) + set_rpc_client_secret_key(rct::rct2sk(rct::skGen())); + ++ // Wallets used to wipe, but not erase, old unused multisig key info, which lead to huge memory leaks. ++ // Here we erase these multisig keys if they're zero'd out to free up space. ++ for (auto &td : m_transfers) ++ { ++ auto mk_it = td.m_multisig_k.begin(); ++ while (mk_it != td.m_multisig_k.end()) ++ { ++ if (*mk_it == rct::zero()) ++ mk_it = td.m_multisig_k.erase(mk_it); ++ else ++ ++mk_it; ++ } ++ } ++ + cryptonote::block genesis; + generate_genesis(genesis); + crypto::hash genesis_hash = get_block_hash(genesis); @@ -2028,6 +2113,36 @@ index 83aba6253..56b76c5f9 100644 + } +} +//---------------------------------------------------------------------------------------------------- ++void wallet2::load_wallet_cache(const bool use_fs, const std::string& cache_buf) ++{ ++ boost::system::error_code e; + bool cache_missing = use_fs ? (!boost::filesystem::exists(m_wallet_file, e) || e) : cache_buf.empty(); + if (cache_missing) + { +@@ -6600,7 +6979,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass + bool r = true; + if (use_fs) + { +- load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits::max()); ++ r = load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits::max()); + THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, m_wallet_file); + } + +@@ -6613,7 +6992,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass + THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "internal error: failed to deserialize \"" + m_wallet_file + '\"'); + std::string cache_data; + cache_data.resize(cache_file_data.cache_data.size()); +- crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), m_cache_key, cache_file_data.iv, &cache_data[0]); ++ crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), get_cache_key(), cache_file_data.iv, &cache_data[0]); + + try { + bool loaded = false; +@@ -6703,60 +7082,76 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass + m_account_public_address.m_view_public_key != m_account.get_keys().m_account_address.m_view_public_key, + error::wallet_files_doesnt_correspond, m_keys_file, m_wallet_file); + } ++} ++//---------------------------------------------------------------------------------------------------- +void wallet2::process_background_cache_on_open() +{ + if (m_wallet_file.empty()) @@ -2036,17 +2151,25 @@ index 83aba6253..56b76c5f9 100644 + return; + if (m_background_sync_type == BackgroundSyncOff) + return; + +- if (!m_persistent_rpc_client_id) +- set_rpc_client_secret_key(rct::rct2sk(rct::skGen())); + if (m_background_sync_type == BackgroundSyncReusePassword) + { + const background_sync_data_t background_sync_data = m_background_sync_data; + const hashchain blockchain = m_blockchain; + process_background_cache(background_sync_data, blockchain, m_last_block_reward); -+ + +- // Wallets used to wipe, but not erase, old unused multisig key info, which lead to huge memory leaks. +- // Here we erase these multisig keys if they're zero'd out to free up space. +- for (auto &td : m_transfers) + // Reset the background cache after processing + reset_background_sync_data(m_background_sync_data); + } + else if (m_background_sync_type == BackgroundSyncCustomPassword) -+ { + { +- auto mk_it = td.m_multisig_k.begin(); +- while (mk_it != td.m_multisig_k.end()) + // If the background wallet files don't exist, recreate them + const std::string background_keys_file = make_background_keys_file_name(m_wallet_file); + const std::string background_wallet_file = make_background_wallet_file_name(m_wallet_file); @@ -2057,31 +2180,64 @@ index 83aba6253..56b76c5f9 100644 + THROW_WALLET_EXCEPTION_IF(!m_custom_background_key, error::wallet_internal_error, "Custom background key not set"); + + if (!background_keys_file_exists) -+ { + { +- if (*mk_it == rct::zero()) +- mk_it = td.m_multisig_k.erase(mk_it); +- else +- ++mk_it; + MDEBUG("Background keys file not found, restoring"); + store_background_keys(m_custom_background_key.get()); -+ } -+ + } +- } + +- cryptonote::block genesis; +- generate_genesis(genesis); +- crypto::hash genesis_hash = get_block_hash(genesis); + if (!background_wallet_exists) + { + MDEBUG("Background cache not found, restoring"); + store_background_cache(m_custom_background_key.get(), true/*do_reset_background_sync_data*/); + return; + } -+ + +- if (m_blockchain.empty()) +- { +- m_blockchain.push_back(genesis_hash); +- m_last_block_reward = cryptonote::get_outs_money_amount(genesis.miner_tx); +- } +- else +- { +- check_genesis(genesis_hash); +- } + MDEBUG("Loading background cache"); -+ + +- trim_hashchain(); + // Set up a minimal background wallet2 instance + std::unique_ptr background_w2(new wallet2(m_nettype)); + background_w2->m_is_background_wallet = true; + background_w2->m_background_syncing = true; + background_w2->m_background_sync_type = m_background_sync_type; + background_w2->m_custom_background_key = m_custom_background_key; -+ + +- if (get_num_subaddress_accounts() == 0) +- add_subaddress_account(tr("Primary account")); + cryptonote::account_base account = m_account; + account.forget_spend_key(); + background_w2->m_account = account; -+ + +- try +- { +- find_and_save_rings(false); +- } +- catch (const std::exception &e) +- { +- MERROR("Failed to save rings, will try again next time"); +- } +- +- try +- { +- if (use_fs) +- m_message_store.read_from_file(get_multisig_wallet_state(), m_mms_file, m_load_deprecated_formats); + // Load background cache from file + background_w2->clear(); + background_w2->prepare_file_names(background_wallet_file); @@ -2091,36 +2247,25 @@ index 83aba6253..56b76c5f9 100644 + + // Reset the background cache after processing + store_background_cache(m_custom_background_key.get(), true/*do_reset_background_sync_data*/); -+ } else { -+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, "unknown background sync type"); -+ } -+} -+//---------------------------------------------------------------------------------------------------- -+void wallet2::load_wallet_cache(const bool use_fs, const std::string& cache_buf) -+{ -+ boost::system::error_code e; - bool cache_missing = use_fs ? (!boost::filesystem::exists(m_wallet_file, e) || e) : cache_buf.empty(); - if (cache_missing) + } +- catch (const std::exception &e) ++ else { -@@ -6600,7 +7005,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass - bool r = true; - if (use_fs) - { -- load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits::max()); -+ r = load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits::max()); - THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, m_wallet_file); - } +- MERROR("Failed to initialize MMS, it will be unusable"); ++ THROW_WALLET_EXCEPTION(error::wallet_internal_error, "unknown background sync type"); + } + } + //---------------------------------------------------------------------------------------------------- +@@ -6838,6 +7233,8 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas + same_file = canonical_old_path == canonical_new_path; + } -@@ -6613,7 +7018,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass - THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "internal error: failed to deserialize \"" + m_wallet_file + '\"'); - std::string cache_data; - cache_data.resize(cache_file_data.cache_data.size()); -- crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), m_cache_key, cache_file_data.iv, &cache_data[0]); -+ crypto::chacha20(cache_file_data.cache_data.data(), cache_file_data.cache_data.size(), get_cache_key(), cache_file_data.iv, &cache_data[0]); ++ THROW_WALLET_EXCEPTION_IF(m_is_background_wallet && !same_file, error::wallet_internal_error, ++ "Cannot save background wallet files to a different location"); - try { - bool loaded = false; -@@ -6854,6 +7259,21 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas + if (!same_file) + { +@@ -6854,6 +7251,21 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas } } } @@ -2142,7 +2287,7 @@ index 83aba6253..56b76c5f9 100644 // get wallet cache data boost::optional cache_file_data = get_cache_file_data(); -@@ -6947,6 +7367,22 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas +@@ -6947,6 +7359,22 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas // store should only exist if the MMS is really active m_message_store.write_to_file(get_multisig_wallet_state(), m_mms_file); } @@ -2165,7 +2310,7 @@ index 83aba6253..56b76c5f9 100644 } //---------------------------------------------------------------------------------------------------- boost::optional wallet2::get_cache_file_data() -@@ -6964,7 +7400,7 @@ boost::optional wallet2::get_cache_file_data() +@@ -6964,7 +7392,7 @@ boost::optional wallet2::get_cache_file_data() std::string cipher; cipher.resize(cache_file_data.get().cache_data.size()); cache_file_data.get().iv = crypto::rand(); @@ -2174,7 +2319,7 @@ index 83aba6253..56b76c5f9 100644 cache_file_data.get().cache_data = cipher; return cache_file_data; } -@@ -9034,6 +9470,34 @@ bool wallet2::is_keys_file_locked() const +@@ -9034,6 +9462,34 @@ bool wallet2::is_keys_file_locked() const return m_keys_file_locker->locked(); } @@ -2209,7 +2354,7 @@ index 83aba6253..56b76c5f9 100644 bool wallet2::tx_add_fake_output(std::vector> &outs, uint64_t global_index, const crypto::public_key& output_public_key, const rct::key& mask, uint64_t real_index, bool unlocked, std::unordered_set &valid_public_keys_cache) const { if (!unlocked) // don't add locked outs -@@ -14380,6 +14844,408 @@ bool wallet2::import_key_images(signed_tx_set & signed_tx, size_t offset, bool o +@@ -14380,6 +14836,413 @@ bool wallet2::import_key_images(signed_tx_set & signed_tx, size_t offset, bool o return import_key_images(signed_tx.key_images, offset, only_selected_transfers ? boost::make_optional(selected_transfers) : boost::none); } @@ -2292,9 +2437,9 @@ index 83aba6253..56b76c5f9 100644 + // Sort background synced txs in the order they appeared in the cache so that + // we process them in the order they appeared in the chain. Thus if tx2 spends + // from tx1, we will know because tx1 is processed before tx2. -+ std::vector> sorted_bgs_cache(background_sync_data.txs.begin(), background_sync_data.txs.end()); ++ std::vector> sorted_bgs_cache(background_sync_data.txs.begin(), background_sync_data.txs.end()); + std::sort(sorted_bgs_cache.begin(), sorted_bgs_cache.end(), -+ [](const std::pair& l, const std::pair& r) ++ [](const std::pair& l, const std::pair& r) + { + uint64_t left_index = l.second.index_in_background_sync_data; + uint64_t right_index = r.second.index_in_background_sync_data; @@ -2357,6 +2502,8 @@ index 83aba6253..56b76c5f9 100644 + + THROW_WALLET_EXCEPTION_IF(m_background_sync_type != BackgroundSyncCustomPassword, error::wallet_internal_error, + "Can only write a background cache when using a custom background password"); ++ THROW_WALLET_EXCEPTION_IF(m_wallet_file.empty(), error::wallet_internal_error, ++ "No wallet file known, can't store background cache"); + + std::unique_ptr background_w2(new wallet2(m_nettype)); + background_w2->prepare_file_names(make_background_wallet_file_name(m_wallet_file)); @@ -2395,6 +2542,9 @@ index 83aba6253..56b76c5f9 100644 +{ + MDEBUG("Storing background keys"); + ++ THROW_WALLET_EXCEPTION_IF(m_wallet_file.empty(), error::wallet_internal_error, ++ "No wallet file known, can't store background keys"); ++ + const std::string background_keys_file = make_background_keys_file_name(m_wallet_file); + bool r = store_keys(background_keys_file, custom_background_key, false/*watch_only*/, true/*background_keys_file*/); + THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, background_keys_file); @@ -2619,7 +2769,7 @@ index 83aba6253..56b76c5f9 100644 { payment_container payments; diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h -index db5c1feb3..74bb867c1 100644 +index db5c1feb3..2f2664f8e 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -257,6 +257,20 @@ private: @@ -2661,7 +2811,7 @@ index db5c1feb3..74bb867c1 100644 END_SERIALIZE() }; -+ struct background_synced_tx ++ struct background_synced_tx_t + { + uint64_t index_in_background_sync_data; + cryptonote::transaction tx; @@ -2687,9 +2837,9 @@ index db5c1feb3..74bb867c1 100644 + + struct background_sync_data_t + { -+ bool first_refresh_done; -+ uint64_t start_height; -+ serializable_unordered_map txs; ++ bool first_refresh_done = false; ++ uint64_t start_height = 0; ++ serializable_unordered_map txs; + + // Relevant wallet settings + uint64_t wallet_refresh_from_block_height; @@ -2730,31 +2880,39 @@ index db5c1feb3..74bb867c1 100644 bool has_multisig_partial_key_images() const; bool has_unknown_key_images() const; bool get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase = std::string()) const; -@@ -1301,6 +1370,11 @@ private: +@@ -1301,11 +1370,17 @@ private: return; } a & m_has_ever_refreshed_from_node; -+ if ((m_background_sync_type == BackgroundSyncCustomPassword && m_is_background_wallet) || -+ (m_background_sync_type == BackgroundSyncReusePassword && !m_is_background_wallet)) ++ if(ver < 31) + { -+ a & m_background_sync_data; ++ m_background_sync_data = background_sync_data_t{}; ++ return; + } ++ a & m_background_sync_data; } BEGIN_SERIALIZE_OBJECT() -@@ -1337,6 +1411,11 @@ private: + MAGIC_FIELD("wownero wallet cache") +- VERSION_FIELD(1) ++ VERSION_FIELD(2) + FIELD(m_blockchain) + FIELD(m_transfers) + FIELD(m_account_public_address) +@@ -1337,6 +1412,12 @@ private: return true; } FIELD(m_has_ever_refreshed_from_node) -+ if ((m_background_sync_type == BackgroundSyncCustomPassword && m_is_background_wallet) || -+ (m_background_sync_type == BackgroundSyncReusePassword && !m_is_background_wallet)) ++ if (version < 2) + { -+ FIELD(m_background_sync_data) ++ m_background_sync_data = background_sync_data_t{}; ++ return true; + } ++ FIELD(m_background_sync_data) END_SERIALIZE() /*! -@@ -1352,6 +1431,8 @@ private: +@@ -1352,6 +1433,8 @@ private: * \return Whether path is valid format */ static bool wallet_valid_path_format(const std::string& file_path); @@ -2763,7 +2921,7 @@ index db5c1feb3..74bb867c1 100644 static bool parse_long_payment_id(const std::string& payment_id_str, crypto::hash& payment_id); static bool parse_short_payment_id(const std::string& payment_id_str, crypto::hash8& payment_id); static bool parse_payment_id(const std::string& payment_id_str, crypto::hash& payment_id); -@@ -1400,6 +1481,9 @@ private: +@@ -1400,6 +1483,9 @@ private: void ignore_outputs_below(uint64_t value) { m_ignore_outputs_below = value; } bool track_uses() const { return m_track_uses; } void track_uses(bool value) { m_track_uses = value; } @@ -2773,24 +2931,15 @@ index db5c1feb3..74bb867c1 100644 bool show_wallet_name_when_locked() const { return m_show_wallet_name_when_locked; } void show_wallet_name_when_locked(bool value) { m_show_wallet_name_when_locked = value; } bool show_detailed_prompt() const { return m_show_detailed_prompt; } -@@ -1428,6 +1512,7 @@ private: - void enable_multisig(bool enable) { m_enable_multisig = enable; } - bool is_mismatched_daemon_version_allowed() const { return m_allow_mismatched_daemon_version; } - void allow_mismatched_daemon_version(bool allow_mismatch) { m_allow_mismatched_daemon_version = allow_mismatch; } -+ uint64_t kdf_rounds() const { return m_kdf_rounds; }; - - bool get_tx_key_cached(const crypto::hash &txid, crypto::secret_key &tx_key, std::vector &additional_tx_keys) const; - void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector &additional_tx_keys, const boost::optional &single_destination_subaddress = boost::none); -@@ -1718,6 +1803,9 @@ private: - uint64_t get_bytes_sent() const; - uint64_t get_bytes_received() const; - +@@ -1738,6 +1824,8 @@ private: + std::string printTxPrefix(const cryptonote::transaction_prefix &tx); + std::string printPaymentDetails(const payment_details &pd); + std::string printTxDestinationEntry(const cryptonote::tx_destination_entry &tx); + void start_background_sync(); + void stop_background_sync(const epee::wipeable_string &wallet_password, const crypto::secret_key &spend_secret_key = crypto::null_skey); -+ - std::string printBlockchain(); - std::string printTransfers(); - std::string printKeyImages(); + + // MMS ------------------------------------------------------------------------------------------------- + mms::message_store& get_message_store() { return m_message_store; }; @@ -1775,6 +1863,9 @@ private: * \return Whether it was successful. */ @@ -2809,15 +2958,23 @@ index db5c1feb3..74bb867c1 100644 void process_new_transaction(const crypto::hash &txid, const cryptonote::transaction& tx, const std::vector &o_indices, uint64_t height, uint8_t block_version, uint64_t ts, bool miner_tx, bool pool, bool double_spend_seen, const tx_cache_data &tx_cache_data, std::map, size_t> *output_tracker_cache = NULL, bool ignore_callbacks = false); bool should_skip_block(const cryptonote::block &b, uint64_t height) const; void process_new_blockchain_entry(const cryptonote::block& b, const cryptonote::block_complete_entry& bche, const parsed_block &parsed_block, const crypto::hash& bl_id, uint64_t height, const std::vector &tx_cache_data, size_t tx_cache_data_offset, std::map, size_t> *output_tracker_cache = NULL); -@@ -1796,6 +1888,7 @@ private: +@@ -1796,6 +1888,15 @@ private: void get_short_chain_history(std::list& ids, uint64_t granularity = 1) const; bool clear(); void clear_soft(bool keep_key_images=false); ++ /* ++ * clear_user_data clears data created by the user, which is mostly data ++ * that a view key cannot identify on chain. This function was initially ++ * added to ensure that a "background" wallet (a wallet that syncs with just ++ * a view key hot in memory) does not have any sensitive data loaded that it ++ * does not need in order to sync. Future devs should take care to ensure ++ * that this function deletes data that is not useful for background syncing ++ */ + void clear_user_data(); void pull_blocks(bool first, bool try_incremental, uint64_t start_height, uint64_t& blocks_start_height, const std::list &short_chain_history, std::vector &blocks, std::vector &o_indices, uint64_t ¤t_height); void pull_hashes(uint64_t start_height, uint64_t& blocks_start_height, const std::list &short_chain_history, std::vector &hashes); void fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list &short_chain_history, bool force = false); -@@ -1847,10 +1940,23 @@ private: +@@ -1847,10 +1948,23 @@ private: bool get_ring(const crypto::chacha_key &key, const crypto::key_image &key_image, std::vector &outs); crypto::chacha_key get_ringdb_key(); void setup_keys(const epee::wipeable_string &password); @@ -2841,19 +2998,16 @@ index db5c1feb3..74bb867c1 100644 void register_devices(); hw::device& lookup_device(const std::string & device_descriptor); -@@ -1966,6 +2072,11 @@ private: +@@ -1966,6 +2080,8 @@ private: uint64_t m_ignore_outputs_above; uint64_t m_ignore_outputs_below; bool m_track_uses; + bool m_is_background_wallet; + BackgroundSyncType m_background_sync_type; -+ bool m_background_syncing; -+ bool m_processing_background_cache; -+ background_sync_data_t m_background_sync_data; bool m_show_wallet_name_when_locked; bool m_show_detailed_prompt; uint32_t m_inactivity_lock_timeout; -@@ -2012,6 +2123,7 @@ private: +@@ -2012,6 +2128,7 @@ private: uint64_t m_last_block_reward; std::unique_ptr m_keys_file_locker; @@ -2861,7 +3015,7 @@ index db5c1feb3..74bb867c1 100644 mms::message_store m_message_store; bool m_original_keys_available; -@@ -2019,6 +2131,7 @@ private: +@@ -2019,6 +2136,7 @@ private: crypto::secret_key m_original_view_secret_key; crypto::chacha_key m_cache_key; @@ -2869,22 +3023,37 @@ index db5c1feb3..74bb867c1 100644 std::shared_ptr m_encrypt_keys_after_refresh; bool m_unattended; -@@ -2052,6 +2165,8 @@ BOOST_CLASS_VERSION(tools::wallet2::signed_tx_set, 1) +@@ -2034,9 +2152,13 @@ private: + + static boost::mutex default_daemon_address_lock; + static std::string default_daemon_address; ++ ++ bool m_background_syncing; ++ bool m_processing_background_cache; ++ background_sync_data_t m_background_sync_data; + }; + } +-BOOST_CLASS_VERSION(tools::wallet2, 30) ++BOOST_CLASS_VERSION(tools::wallet2, 31) + BOOST_CLASS_VERSION(tools::wallet2::transfer_details, 12) + BOOST_CLASS_VERSION(tools::wallet2::multisig_info, 1) + BOOST_CLASS_VERSION(tools::wallet2::multisig_info::LR, 0) +@@ -2052,6 +2174,8 @@ BOOST_CLASS_VERSION(tools::wallet2::signed_tx_set, 1) BOOST_CLASS_VERSION(tools::wallet2::tx_construction_data, 4) BOOST_CLASS_VERSION(tools::wallet2::pending_tx, 3) BOOST_CLASS_VERSION(tools::wallet2::multisig_sig, 1) -+BOOST_CLASS_VERSION(tools::wallet2::background_synced_tx, 0) ++BOOST_CLASS_VERSION(tools::wallet2::background_synced_tx_t, 0) +BOOST_CLASS_VERSION(tools::wallet2::background_sync_data_t, 0) namespace boost { -@@ -2550,6 +2665,29 @@ namespace boost +@@ -2550,6 +2674,29 @@ namespace boost return; a & x.multisig_sigs; } + + template -+ inline void serialize(Archive& a, tools::wallet2::background_synced_tx &x, const boost::serialization::version_type ver) ++ inline void serialize(Archive& a, tools::wallet2::background_synced_tx_t &x, const boost::serialization::version_type ver) + { + a & x.index_in_background_sync_data; + a & x.tx; @@ -3534,7 +3703,7 @@ index 734229380..b964036bd 100644 +#define WALLET_RPC_ERROR_CODE_IS_BACKGROUND_WALLET -49 +#define WALLET_RPC_ERROR_CODE_IS_BACKGROUND_SYNCING -50 diff --git a/tests/functional_tests/transfer.py b/tests/functional_tests/transfer.py -index 4063911f4..39ee86df3 100755 +index 4063911f4..60eb09a10 100755 --- a/tests/functional_tests/transfer.py +++ b/tests/functional_tests/transfer.py @@ -30,6 +30,7 @@ @@ -3572,19 +3741,28 @@ index 4063911f4..39ee86df3 100755 def reset(self): print('Resetting blockchain') -@@ -71,6 +85,387 @@ class TransferTest(): - daemon.pop_blocks(res.height - 1) - daemon.flush_txpool() +@@ -840,12 +854,6 @@ class TransferTest(): + + print('Testing scan_tx') + +- def diff_transfers(actual_transfers, expected_transfers): +- diff = DeepDiff(actual_transfers, expected_transfers) +- if diff != {}: +- pp.pprint(diff) +- assert diff == {} +- + # set up sender_wallet + sender_wallet = self.wallet[0] + try: sender_wallet.close_wallet() +@@ -1127,5 +1135,385 @@ class TransferTest(): + except AssertionError: + pass + def check_background_sync(self): + daemon = Daemon() + + print('Testing background sync') + -+ # Background sync type options -+ REUSE_PASSWORD = 'reuse-wallet-password' -+ CUSTOM_PASSWORD = 'custom-background-password' -+ + # Some helper functions + def stop_with_wrong_inputs(wallet, wallet_password, seed = ''): + invalid = False @@ -3631,6 +3809,10 @@ index 4063911f4..39ee86df3 100755 + out_len = 0 if 'out' not in res else len(res.out) + sender_starting_balance = sender_wallet.get_balance().balance + ++ # Background sync type options ++ reuse_password = sender_wallet.background_sync_options.reuse_password ++ custom_password = sender_wallet.background_sync_options.custom_password ++ + # set up receiver_wallet + receiver_wallet = self.wallet[1] + try: receiver_wallet.close_wallet() @@ -3655,7 +3837,7 @@ index 4063911f4..39ee86df3 100755 + expected_receiver_balance = receiver_starting_balance + (amount - fee) + + print('Checking background sync on outgoing wallet') -+ sender_wallet.setup_background_sync(background_sync_type = REUSE_PASSWORD) ++ sender_wallet.setup_background_sync(background_sync_type = reuse_password) + sender_wallet.start_background_sync() + # Mine block to an uninvolved wallet + daemon.generateblocks('46r4nYSevkfBUMhuykdK3gQ98XDqDTYW1hNLaXNvjpsJaSbNtdXh1sKMsdVgqkaihChAzEy29zEDPMR3NHQvGoZCLGwTerK', 1) @@ -3680,7 +3862,7 @@ index 4063911f4..39ee86df3 100755 + + # Restore and check background syncing outgoing wallet + restore_wallet(sender_wallet, seeds[0]) -+ sender_wallet.setup_background_sync(background_sync_type = REUSE_PASSWORD) ++ sender_wallet.setup_background_sync(background_sync_type = reuse_password) + sender_wallet.start_background_sync() + sender_wallet.refresh() + for i, out_tx in enumerate(transfers.out): @@ -3706,9 +3888,9 @@ index 4063911f4..39ee86df3 100755 + assert_correct_transfers(sender_wallet, transfers, incoming_transfers, expected_sender_balance) + + # Check stopping a wallet with wallet files saved to disk -+ for background_sync_type in [REUSE_PASSWORD, CUSTOM_PASSWORD]: ++ for background_sync_type in [reuse_password, custom_password]: + restore_wallet(sender_wallet, seeds[0], 'test1', 'test_password') -+ background_cache_password = None if background_sync_type == REUSE_PASSWORD else 'background_password' ++ background_cache_password = None if background_sync_type == reuse_password else 'background_password' + sender_wallet.setup_background_sync(background_sync_type = background_sync_type, wallet_password = 'test_password', background_cache_password = background_cache_password) + sender_wallet.start_background_sync() + sender_wallet.refresh() @@ -3718,9 +3900,9 @@ index 4063911f4..39ee86df3 100755 + assert_correct_transfers(sender_wallet, transfers, incoming_transfers, expected_sender_balance) + + # Close wallet while background syncing, then reopen -+ for background_sync_type in [REUSE_PASSWORD, CUSTOM_PASSWORD]: ++ for background_sync_type in [reuse_password, custom_password]: + restore_wallet(sender_wallet, seeds[0], 'test1', 'test_password') -+ background_cache_password = None if background_sync_type == REUSE_PASSWORD else 'background_password' ++ background_cache_password = None if background_sync_type == reuse_password else 'background_password' + sender_wallet.setup_background_sync(background_sync_type = background_sync_type, wallet_password = 'test_password', background_cache_password = background_cache_password) + sender_wallet.start_background_sync() + sender_wallet.refresh() @@ -3732,9 +3914,9 @@ index 4063911f4..39ee86df3 100755 + assert_correct_transfers(sender_wallet, transfers, incoming_transfers, expected_sender_balance) + + # Close wallet while syncing normally, then reopen -+ for background_sync_type in [REUSE_PASSWORD, CUSTOM_PASSWORD]: ++ for background_sync_type in [reuse_password, custom_password]: + restore_wallet(sender_wallet, seeds[0], 'test1', 'test_password') -+ background_cache_password = None if background_sync_type == REUSE_PASSWORD else 'background_password' ++ background_cache_password = None if background_sync_type == reuse_password else 'background_password' + sender_wallet.setup_background_sync(background_sync_type = background_sync_type, wallet_password = 'test_password', background_cache_password = background_cache_password) + sender_wallet.refresh() + assert_correct_transfers(sender_wallet, transfers, incoming_transfers, expected_sender_balance) @@ -3748,7 +3930,7 @@ index 4063911f4..39ee86df3 100755 + restore_wallet(sender_wallet, seeds[0], 'test1', 'test_password') + assert not util_resources.file_exists('test1.background') + assert not util_resources.file_exists('test1.background.keys') -+ sender_wallet.setup_background_sync(background_sync_type = CUSTOM_PASSWORD, wallet_password = 'test_password', background_cache_password = background_cache_password) ++ sender_wallet.setup_background_sync(background_sync_type = custom_password, wallet_password = 'test_password', background_cache_password = background_cache_password) + assert util_resources.file_exists('test1.background') + assert util_resources.file_exists('test1.background.keys') + sender_wallet.close_wallet() @@ -3774,18 +3956,18 @@ index 4063911f4..39ee86df3 100755 + assert not util_resources.file_exists('test1.background') + assert not util_resources.file_exists('test1.background.keys') + same_password = False -+ try: sender_wallet.setup_background_sync(background_sync_type = CUSTOM_PASSWORD, wallet_password = 'test_password', background_cache_password = 'test_password') ++ try: sender_wallet.setup_background_sync(background_sync_type = custom_password, wallet_password = 'test_password', background_cache_password = 'test_password') + except: same_password = True + assert same_password + assert not util_resources.file_exists('test1.background') + assert not util_resources.file_exists('test1.background.keys') + + # Turn off background sync -+ for background_sync_type in [REUSE_PASSWORD, CUSTOM_PASSWORD]: ++ for background_sync_type in [reuse_password, custom_password]: + restore_wallet(sender_wallet, seeds[0], 'test1', 'test_password') -+ background_cache_password = None if background_sync_type == REUSE_PASSWORD else 'background_password' ++ background_cache_password = None if background_sync_type == reuse_password else 'background_password' + sender_wallet.setup_background_sync(background_sync_type = background_sync_type, wallet_password = 'test_password', background_cache_password = background_cache_password) -+ if background_sync_type == CUSTOM_PASSWORD: ++ if background_sync_type == custom_password: + assert util_resources.file_exists('test1.background') + assert util_resources.file_exists('test1.background.keys') + sender_wallet.close_wallet() @@ -3798,7 +3980,7 @@ index 4063911f4..39ee86df3 100755 + assert not util_resources.file_exists('test1.background') + assert not util_resources.file_exists('test1.background.keys') + sender_wallet.open_wallet('test1', password = 'test_password') -+ sender_wallet.setup_background_sync(background_sync_type = 'off', wallet_password = 'test_password') ++ sender_wallet.setup_background_sync(background_sync_type = sender_wallet.background_sync_options.off, wallet_password = 'test_password') + assert not util_resources.file_exists('test1.background') + assert not util_resources.file_exists('test1.background.keys') + sender_wallet.close_wallet() @@ -3813,7 +3995,7 @@ index 4063911f4..39ee86df3 100755 + assert_correct_transfers(sender_wallet, transfers, incoming_transfers, expected_sender_balance) + + print('Checking background sync on incoming wallet') -+ receiver_wallet.setup_background_sync(background_sync_type = REUSE_PASSWORD) ++ receiver_wallet.setup_background_sync(background_sync_type = reuse_password) + receiver_wallet.start_background_sync() + receiver_wallet.refresh() + transfers = receiver_wallet.get_transfers() @@ -3831,7 +4013,7 @@ index 4063911f4..39ee86df3 100755 + + # Restore and check background syncing incoming wallet + restore_wallet(receiver_wallet, seeds[1]) -+ receiver_wallet.setup_background_sync(background_sync_type = REUSE_PASSWORD) ++ receiver_wallet.setup_background_sync(background_sync_type = reuse_password) + receiver_wallet.start_background_sync() + receiver_wallet.refresh() + if 'out' in transfers: @@ -3858,7 +4040,7 @@ index 4063911f4..39ee86df3 100755 + + # Check a fresh incoming wallet with wallet files saved to disk and encrypted with password + restore_wallet(receiver_wallet, seeds[1], 'test2', 'test_password') -+ receiver_wallet.setup_background_sync(background_sync_type = REUSE_PASSWORD, wallet_password = 'test_password') ++ receiver_wallet.setup_background_sync(background_sync_type = reuse_password, wallet_password = 'test_password') + receiver_wallet.start_background_sync() + receiver_wallet.refresh() + assert_correct_transfers(receiver_wallet, background_transfers, background_incoming_transfers, background_bal) @@ -3868,7 +4050,7 @@ index 4063911f4..39ee86df3 100755 + + # Close receiver's wallet while background sync is enabled then reopen + restore_wallet(receiver_wallet, seeds[1], 'test2', 'test_password') -+ receiver_wallet.setup_background_sync(background_sync_type = REUSE_PASSWORD, wallet_password = 'test_password') ++ receiver_wallet.setup_background_sync(background_sync_type = reuse_password, wallet_password = 'test_password') + receiver_wallet.start_background_sync() + receiver_wallet.refresh() + diff_transfers(receiver_wallet.get_transfers(), background_transfers) @@ -3901,12 +4083,12 @@ index 4063911f4..39ee86df3 100755 + daemon.out_peers(0) + + # Background sync type options -+ REUSE_PASSWORD = 'reuse-wallet-password' -+ CUSTOM_PASSWORD = 'custom-background-password' ++ sender_wallet = self.wallet[0] ++ reuse_password = sender_wallet.background_sync_options.reuse_password ++ custom_password = sender_wallet.background_sync_options.custom_password + -+ for background_sync_type in [REUSE_PASSWORD, CUSTOM_PASSWORD]: ++ for background_sync_type in [reuse_password, custom_password]: + # Set up wallet saved to disk -+ sender_wallet = self.wallet[0] + sender_wallet.close_wallet() + util_resources.remove_wallet_files('test1') + sender_wallet.restore_deterministic_wallet(seed = seeds[0], filename = 'test1', password = '') @@ -3934,7 +4116,7 @@ index 4063911f4..39ee86df3 100755 + assert sender_wallet.get_balance().balance < (sender_starting_balance - amount) + + # Pop the block while background syncing -+ background_cache_password = None if background_sync_type == REUSE_PASSWORD else 'background_password' ++ background_cache_password = None if background_sync_type == reuse_password else 'background_password' + sender_wallet.setup_background_sync(background_sync_type = background_sync_type, wallet_password = '', background_cache_password = background_cache_password) + sender_wallet.start_background_sync() + daemon.pop_blocks(1) @@ -3956,25 +4138,10 @@ index 4063911f4..39ee86df3 100755 + self.wallet[0].close_wallet() + self.wallet[0].restore_deterministic_wallet(seed = seeds[0]) + -+ - def create(self): - print('Creating wallets') - self.wallet = [None] * len(seeds) -@@ -840,12 +1235,6 @@ class TransferTest(): - - print('Testing scan_tx') - -- def diff_transfers(actual_transfers, expected_transfers): -- diff = DeepDiff(actual_transfers, expected_transfers) -- if diff != {}: -- pp.pprint(diff) -- assert diff == {} -- - # set up sender_wallet - sender_wallet = self.wallet[0] - try: sender_wallet.close_wallet() + if __name__ == '__main__': + TransferTest().run_test() diff --git a/tests/functional_tests/util_resources.py b/tests/functional_tests/util_resources.py -index e030312da..3197187f4 100755 +index e030312da..3ca6fdb86 100755 --- a/tests/functional_tests/util_resources.py +++ b/tests/functional_tests/util_resources.py @@ -37,6 +37,8 @@ @@ -4006,7 +4173,7 @@ index e030312da..3197187f4 100755 + return WALLET_DIRECTORY + '/' + name + +def remove_wallet_files(name): -+ for suffix in ['', '.keys', '.background', '.background.keys']: ++ for suffix in ['', '.keys', '.background', '.background.keys', '.address.txt']: + remove_file(name + suffix) + +def file_exists(name): @@ -4125,15 +4292,22 @@ index ef6964f9e..25121a02e 100644 + ASSERT_TRUE(str == std::string("foo")); +} diff --git a/utils/python-rpc/framework/wallet.py b/utils/python-rpc/framework/wallet.py -index 1e10e1f86..ccf6ca93e 100644 +index 1e10e1f86..bff33a561 100644 --- a/utils/python-rpc/framework/wallet.py +++ b/utils/python-rpc/framework/wallet.py -@@ -1138,3 +1138,38 @@ class Wallet(object): +@@ -1138,3 +1138,45 @@ class Wallet(object): 'id': '0' } return self.rpc.send_json_rpc_request(frozen) + -+ def setup_background_sync(self, background_sync_type = 'off', wallet_password = '', background_cache_password = ''): ++ class BackgroundSyncOptions(object): ++ def __init__(self): ++ self.off = 'off' ++ self.reuse_password = 'reuse-wallet-password' ++ self.custom_password = 'custom-background-password' ++ background_sync_options = BackgroundSyncOptions() ++ ++ def setup_background_sync(self, background_sync_type = background_sync_options.off, wallet_password = '', background_cache_password = ''): + setup_background_sync = { + 'method': 'setup_background_sync', + 'jsonrpc': '2.0', @@ -4167,3 +4341,6 @@ index 1e10e1f86..ccf6ca93e 100644 + 'id': '0' + } + return self.rpc.send_json_rpc_request(stop_background_sync) +-- +2.44.0 + diff --git a/patches/monero/0002-airgap.patch b/patches/wownero/0004-airgap.patch similarity index 77% rename from patches/monero/0002-airgap.patch rename to patches/wownero/0004-airgap.patch index c3ce71b..a6fdda5 100644 --- a/patches/monero/0002-airgap.patch +++ b/patches/wownero/0004-airgap.patch @@ -1,21 +1,21 @@ -From 559780d053549f01e9153bf43bad24c80255117d Mon Sep 17 00:00:00 2001 +From 60c89b5c4e2e874e725915ed0a8b7709849ef140 Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto -Date: Tue, 12 Mar 2024 10:09:50 +0100 -Subject: [PATCH] PATCH: airgap +Date: Tue, 26 Mar 2024 09:06:32 +0100 +Subject: [PATCH 4/9] airgap --- - src/wallet/api/wallet.cpp | 23 ++++++++++++++++++++++ + src/wallet/api/wallet.cpp | 23 +++++++++++++++++++++++ src/wallet/api/wallet.h | 2 ++ src/wallet/api/wallet2_api.h | 3 +++ - src/wallet/wallet2.cpp | 38 ++++++++++++++++++++++++++++++------ + src/wallet/wallet2.cpp | 28 ++++++++++++++++++++++------ src/wallet/wallet2.h | 1 + - 5 files changed, 61 insertions(+), 6 deletions(-) + 5 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp -index 1a9c6f674..42887dced 100644 +index 5ef3132d2..1c9a709d4 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp -@@ -1129,6 +1129,24 @@ uint64_t WalletImpl::unlockedBalance(uint32_t accountIndex) const +@@ -1172,6 +1172,24 @@ uint64_t WalletImpl::unlockedBalance(uint32_t accountIndex) const return m_wallet->unlocked_balance(accountIndex, false); } @@ -40,7 +40,7 @@ index 1a9c6f674..42887dced 100644 uint64_t WalletImpl::blockChainHeight() const { if(m_wallet->light_wallet()) { -@@ -1291,6 +1309,11 @@ bool WalletImpl::submitTransaction(const string &fileName) { +@@ -1376,6 +1394,11 @@ bool WalletImpl::submitTransaction(const string &fileName) { return true; } @@ -53,10 +53,10 @@ index 1a9c6f674..42887dced 100644 { if (m_wallet->watch_only()) diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h -index 9acd2871f..05d065c5c 100644 +index fc6341861..7b885e866 100644 --- a/src/wallet/api/wallet.h +++ b/src/wallet/api/wallet.h -@@ -122,6 +122,7 @@ public: +@@ -130,6 +130,7 @@ public: bool setProxy(const std::string &address) override; uint64_t balance(uint32_t accountIndex = 0) const override; uint64_t unlockedBalance(uint32_t accountIndex = 0) const override; @@ -64,19 +64,19 @@ index 9acd2871f..05d065c5c 100644 uint64_t blockChainHeight() const override; uint64_t approximateBlockChainHeight() const override; uint64_t estimateBlockChainHeight() const override; -@@ -175,6 +176,7 @@ public: - virtual PendingTransaction * createSweepUnmixableTransaction() override; - bool submitTransaction(const std::string &fileName) override; +@@ -190,6 +191,7 @@ public: virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override; + virtual UnsignedTransaction * loadUnsignedTxFromStr(const std::string &unsigned_tx) override; + virtual UnsignedTransaction * loadUnsignedTxFromBase64Str(const std::string &unsigned_tx) override; + bool hasUnknownKeyImages() const override; + virtual PendingTransaction * loadSignedTx(const std::string &signed_filename) override; bool exportKeyImages(const std::string &filename, bool all = false) override; bool importKeyImages(const std::string &filename) override; - bool exportOutputs(const std::string &filename, bool all = false) override; diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h -index 4268b656e..4edaefefd 100644 +index 626c63fc5..39b942ef4 100644 --- a/src/wallet/api/wallet2_api.h +++ b/src/wallet/api/wallet2_api.h -@@ -626,6 +626,7 @@ struct Wallet +@@ -726,6 +726,7 @@ struct Wallet result += unlockedBalance(i); return result; } @@ -84,7 +84,7 @@ index 4268b656e..4edaefefd 100644 /** * @brief watchOnly - checks if wallet is watch only -@@ -910,6 +911,8 @@ struct Wallet +@@ -1045,6 +1046,8 @@ struct Wallet virtual uint64_t estimateTransactionFee(const std::vector> &destinations, PendingTransaction::Priority priority) const = 0; @@ -94,27 +94,10 @@ index 4268b656e..4edaefefd 100644 * \brief exportKeyImages - exports key images to file * \param filename diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp -index 618c43cee..3477e084f 100644 +index d7e2a9699..f996863ff 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp -@@ -947,6 +947,16 @@ uint32_t get_subaddress_clamped_sum(uint32_t idx, uint32_t extra) - return idx + extra; - } - -+bool is_preferred_input(const std::vector& preferred_input_list, const crypto::key_image& input) { -+ if (!preferred_input_list.empty()) { -+ auto it = std::find(preferred_input_list.begin(), preferred_input_list.end(), input); -+ if (it == preferred_input_list.end()) { -+ return false; -+ } -+ } -+ return true; -+} -+ - static void setup_shim(hw::wallet_shim * shim, tools::wallet2 * wallet) - { - shim->get_tx_pub_key_from_received_outs = std::bind(&tools::wallet2::get_tx_pub_key_from_received_outs, wallet, std::placeholders::_1); -@@ -7045,6 +7055,25 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t * +@@ -7432,6 +7432,25 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t * return amount; } //---------------------------------------------------------------------------------------------------- @@ -140,7 +123,7 @@ index 618c43cee..3477e084f 100644 std::map wallet2::balance_per_subaddress(uint32_t index_major, bool strict) const { std::map amount_per_subaddr; -@@ -7895,9 +7924,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector additional_derivations; @@ -151,7 +134,7 @@ index 618c43cee..3477e084f 100644 std::vector additional_tx_pub_keys; for (const crypto::secret_key &skey: txs[n].additional_tx_keys) { -@@ -11295,7 +11322,7 @@ std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_2(std::vector m_ignore_outputs_above || td.amount() < m_ignore_outputs_below) { -@@ -11345,8 +11372,7 @@ std::vector wallet2::create_transactions_2(std::vector wallet2::create_transactions_2(std::vector balance_per_subaddress(uint32_t subaddr_index_major, bool strict) const; std::map>> unlocked_balance_per_subaddress(uint32_t subaddr_index_major, bool strict); +-- +2.44.0 + diff --git a/patches/wownero/0004-coin-control.patch b/patches/wownero/0005-coin-control.patch similarity index 94% rename from patches/wownero/0004-coin-control.patch rename to patches/wownero/0005-coin-control.patch index 45ed9d8..6dcff9f 100644 --- a/patches/wownero/0004-coin-control.patch +++ b/patches/wownero/0005-coin-control.patch @@ -1,7 +1,7 @@ -From 1d12f355eeeba80930f38d398c758154d2d4c340 Mon Sep 17 00:00:00 2001 +From 9f9937ef8f4822c498e10e5bbfc57dfdfb7137f7 Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto Date: Wed, 27 Mar 2024 16:31:36 +0100 -Subject: [PATCH 4/4] coin control +Subject: [PATCH 5/9] coin control --- src/wallet/api/coins.cpp | 62 ++++++++++++++++++++++++++++++++++++ @@ -118,7 +118,7 @@ index 3293d8ae9..bcd8b517f 100644 WalletImpl *m_wallet; std::vector m_rows; diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp -index 63ed26a11..3bbc60d74 100644 +index 1c9a709d4..b935723f7 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -2018,11 +2018,11 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector Date: Tue, 26 Mar 2024 09:44:54 +0100 -Subject: [PATCH] fix build +Subject: [PATCH 6/9] fix build --- contrib/depends/hosts/linux.mk | 8 +++---- @@ -132,3 +132,6 @@ index 000000000..f05cb2b6a + #define POLYSEED_PRIVATE + #else + #ifdef POLYSEED_SHARED +-- +2.44.0 + diff --git a/patches/monero/0005-macos-build-fix.patch b/patches/wownero/0007-macos-build-fix.patch similarity index 97% rename from patches/monero/0005-macos-build-fix.patch rename to patches/wownero/0007-macos-build-fix.patch index 4149a02..10c33d8 100644 --- a/patches/monero/0005-macos-build-fix.patch +++ b/patches/wownero/0007-macos-build-fix.patch @@ -1,7 +1,7 @@ -From b1b150b3de4dd3197c373be39b790c31bb7ddab3 Mon Sep 17 00:00:00 2001 +From 0f3c19706a35798a28eb040858052292a3709312 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 28 Mar 2024 02:03:08 +0100 -Subject: [PATCH] macos build fix +Subject: [PATCH 7/9] macos build fix --- contrib/depends/hosts/darwin.mk | 2 + @@ -111,5 +111,5 @@ index 000000000..a261636e8 +2.39.2 + -- -2.39.2 +2.44.0 diff --git a/patches/wownero/0007-FIX-wallet-listener-crashing.patch b/patches/wownero/0008-FIX-wallet-listener-crashing.patch similarity index 94% rename from patches/wownero/0007-FIX-wallet-listener-crashing.patch rename to patches/wownero/0008-FIX-wallet-listener-crashing.patch index fb92f68..ae5c712 100644 --- a/patches/wownero/0007-FIX-wallet-listener-crashing.patch +++ b/patches/wownero/0008-FIX-wallet-listener-crashing.patch @@ -1,14 +1,14 @@ -From 1286d8b67484dd976997cccd726d4ea9318a6ecd Mon Sep 17 00:00:00 2001 +From a2beff7fc49b80972f78dddedf0ea8c4db145f72 Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto Date: Tue, 2 Apr 2024 11:56:09 +0200 -Subject: [PATCH] FIX: wallet listener crashing +Subject: [PATCH 8/9] FIX: wallet listener crashing --- src/wallet/api/wallet.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp -index 3bbc60d74..b42289842 100644 +index b935723f7..432ca4fbf 100644 --- a/src/wallet/api/wallet.cpp +++ b/src/wallet/api/wallet.cpp @@ -201,8 +201,11 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback diff --git a/patches/wownero/0008-fix-missing-___clear_cache-when-targetting-iOS.patch b/patches/wownero/0009-fix-missing-___clear_cache-when-targetting-iOS.patch similarity index 86% rename from patches/wownero/0008-fix-missing-___clear_cache-when-targetting-iOS.patch rename to patches/wownero/0009-fix-missing-___clear_cache-when-targetting-iOS.patch index c767b9e..e8809cd 100644 --- a/patches/wownero/0008-fix-missing-___clear_cache-when-targetting-iOS.patch +++ b/patches/wownero/0009-fix-missing-___clear_cache-when-targetting-iOS.patch @@ -1,7 +1,7 @@ -From f0c113d77fabc2177296524b78ca262cd4df0b92 Mon Sep 17 00:00:00 2001 +From 8cfcf5b132c41aedbc9c9a0932ffb832cf410761 Mon Sep 17 00:00:00 2001 From: Czarek Nakamoto Date: Tue, 2 Apr 2024 17:07:19 +0200 -Subject: [PATCH] fix missing ___clear_cache when targetting iOS +Subject: [PATCH 9/9] fix missing ___clear_cache when targetting iOS --- .gitmodules | 4 ++-- @@ -29,5 +29,5 @@ index 27b099b6d..6f30d4b92 160000 -Subproject commit 27b099b6dd6fef6e17f58c6dfe00009e9c5df587 +Subproject commit 6f30d4b924fecb231e5b683915cc75d18b3b5866 -- -2.39.2 +2.44.0