summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCzarek Nakamoto <cyjan@mrcyjanek.net>2024-04-12 11:13:43 +0200
committerCzarek Nakamoto <cyjan@mrcyjanek.net>2024-04-12 11:13:43 +0200
commit125e64f11f2201deaf2c291a586211a4410da57a (patch)
tree1f78db1ad19e14e284c128fe5a310edf2d1e1de1
parentb003970d7f445489a588f4d0358af98d995969d2 (diff)
update patchesv0.18.3.3-RC23
update readme
-rw-r--r--patches/monero/0001-polyseed.patch (renamed from patches/wownero/0001-polyseed.patch)180
-rw-r--r--patches/monero/0002-wallet-background-sync-with-just-the-view-key.patch (renamed from patches/monero/0001-background-sync.patch)617
-rw-r--r--patches/monero/0003-airgap.patch (renamed from patches/wownero/0003-airgap.patch)70
-rw-r--r--patches/monero/0004-coin-control.patch (renamed from patches/monero/0003-coin-control.patch)45
-rw-r--r--patches/monero/0005-fix-build-issues.patch (renamed from patches/monero/0004-fix-build.patch)9
-rw-r--r--patches/monero/0006-macos-build-fix.patch (renamed from patches/wownero/0006-macos-build-fix.patch)6
-rw-r--r--patches/monero/0007-fix-make-debug-test-target.patch (renamed from patches/monero/0006-fix-make-debug-test-target.patch)4
-rw-r--r--patches/monero/0008-fix-missing-___clear_cache-when-targetting-iOS.patch (renamed from patches/monero/0007-fix-missing-___clear_cache-when-targetting-iOS.patch)6
-rw-r--r--patches/monero/README.md30
-rw-r--r--patches/wownero/0001-Fix-wallet_api-compilation-target-https-git.wownero..patch (renamed from patches/wownero/0000-fix-wallet_api-compilation-target.patch)7
-rw-r--r--patches/wownero/0002-polyseed-support.patch (renamed from patches/monero/0000-polyseed.patch)180
-rw-r--r--patches/wownero/0003-wallet-background-sync-with-just-the-view-key.patch (renamed from patches/wownero/0002-background-sync.patch)823
-rw-r--r--patches/wownero/0004-airgap.patch (renamed from patches/monero/0002-airgap.patch)70
-rw-r--r--patches/wownero/0005-coin-control.patch (renamed from patches/wownero/0004-coin-control.patch)22
-rw-r--r--patches/wownero/0006-fix-build.patch (renamed from patches/wownero/0005-fix-build.patch)7
-rw-r--r--patches/wownero/0007-macos-build-fix.patch (renamed from patches/monero/0005-macos-build-fix.patch)6
-rw-r--r--patches/wownero/0008-FIX-wallet-listener-crashing.patch (renamed from patches/wownero/0007-FIX-wallet-listener-crashing.patch)6
-rw-r--r--patches/wownero/0009-fix-missing-___clear_cache-when-targetting-iOS.patch (renamed from patches/wownero/0008-fix-missing-___clear_cache-when-targetting-iOS.patch)6
18 files changed, 1232 insertions, 862 deletions
diff --git a/patches/wownero/0001-polyseed.patch b/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 <cyjan@mrcyjanek.net>
-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<Wallet::Device>(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<WalletImpl*>(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::keys_file_data> wallet2::get_keys_file_data(const epee:
+@@ -4629,6 +4646,9 @@ boost::optional<wallet2::keys_file_data> 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<rapidjson::StringBuffer> 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<size_t> select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool allow_rct);
std::vector<size_t> select_available_outputs(const std::function<bool(const transfer_details &td)> &f);
std::vector<size_t> 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<std::string> &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<crypto::public_key> 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
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 <cyjan@mrcyjanek.net>
-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 <justinberman@protonmail.com>
+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<too
+@@ -1105,7 +1107,7 @@ wallet_keys_unlocker::wallet_keys_unlocker(wallet2 &w, const boost::optional<too
boost::lock_guard<boost::mutex> 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<crypto::hash> &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<epee::wipeable_string> 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<unsigned int>(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<std::tuple<cryptonote::transaction, crypto::hash, bool>> &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<std::pair<uint64_t, uint64_
+@@ -4341,8 +4432,12 @@ void wallet2::handle_reorg(uint64_t height, std::map<std::pair<uint64_t, uint64_
+ // C
+ THROW_WALLET_EXCEPTION_IF(height < m_blockchain.offset() && m_blockchain.size() > 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<wallet2::keys_file_data> 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::keys_file_data> 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::keys_file_data> wallet2::get_keys_file_data(const epee:
+@@ -4589,6 +4723,9 @@ boost::optional<wallet2::keys_file_data> 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::keys_file_data> 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::keys_file_data> 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<const char*>(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<size_t>::max());
++ r = load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits<size_t>::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<wallet2> 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<size_t>::max());
-+ r = load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits<size_t>::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<wallet2::cache_file_data> 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::cache_file_data> wallet2::get_cache_file_data()
-@@ -6569,7 +7005,7 @@ boost::optional<wallet2::cache_file_data> wallet2::get_cache_file_data()
+@@ -6569,7 +6997,7 @@ boost::optional<wallet2::cache_file_data> wallet2::get_cache_file_data()
std::string cipher;
cipher.resize(cache_file_data.get().cache_data.size());
cache_file_data.get().iv = crypto::rand<crypto::chacha_iv>();
@@ -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<std::vector<tools::wallet2::get_outs_entry>> &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<crypto::public_key> &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<std::pair<crypto::hash, background_synced_tx>> sorted_bgs_cache(background_sync_data.txs.begin(), background_sync_data.txs.end());
++ std::vector<std::pair<crypto::hash, background_synced_tx_t>> 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<crypto::hash, background_synced_tx>& l, const std::pair<crypto::hash, background_synced_tx>& r)
++ [](const std::pair<crypto::hash, background_synced_tx_t>& l, const std::pair<crypto::hash, background_synced_tx_t>& 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<wallet2> 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<crypto::hash, background_synced_tx> txs;
++ bool first_refresh_done = false;
++ uint64_t start_height = 0;
++ serializable_unordered_map<crypto::hash, background_synced_tx_t> 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<crypto::secret_key> &additional_tx_keys) const;
- void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const boost::optional<cryptonote::account_public_address> &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<crypto::chacha_key>& 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<uint64_t> &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<std::pair<uint64_t, uint64_t>, 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> &tx_cache_data, size_t tx_cache_data_offset, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache = NULL);
-@@ -1770,6 +1862,7 @@ private:
+@@ -1770,6 +1863,15 @@ private:
void get_short_chain_history(std::list<crypto::hash>& 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<crypto::hash> &short_chain_history, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices, uint64_t &current_height);
void pull_hashes(uint64_t start_height, uint64_t& blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::vector<crypto::hash> &hashes);
void fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list<crypto::hash> &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<uint64_t> &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<tools::file_locker> 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<wallet_keys_unlocker> 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 <class Archive>
-+ 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
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 <cyjan@mrcyjanek.net>
-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<std::pair<std::string, uint64_t>> &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<crypto::key_image>& 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<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_major, bool strict) const
{
std::map<uint32_t, uint64_t> amount_per_subaddr;
-@@ -8290,9 +8309,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin
+@@ -7887,9 +7916,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin
crypto::key_derivation derivation;
std::vector<crypto::key_derivation> additional_derivations;
@@ -134,7 +151,7 @@ index 56b76c5f9..00d9c133e 100644
std::vector<crypto::public_key> additional_tx_pub_keys;
for (const crypto::secret_key &skey: txs[n].additional_tx_keys)
{
-@@ -11700,7 +11717,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
+@@ -11287,7 +11314,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is below fractional threshold " << print_money(fractional_threshold));
continue;
}
@@ -143,7 +160,7 @@ index 56b76c5f9..00d9c133e 100644
{
if (td.amount() > m_ignore_outputs_above || td.amount() < m_ignore_outputs_below)
{
-@@ -11750,8 +11767,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
+@@ -11337,8 +11364,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
LOG_PRINT_L2("Starting with " << num_nondust_outputs << " non-dust outputs and " << num_dust_outputs << " dust outputs");
@@ -154,10 +171,10 @@ index 56b76c5f9..00d9c133e 100644
// if empty, put dummy entry so that the front can be referenced later in the loop
if (unused_dust_indices_per_subaddr.empty())
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
-index 74bb867c1..40997cdbb 100644
+index d37332dd1..fc69b3d36 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
-@@ -1173,6 +1173,7 @@ private:
+@@ -1172,6 +1172,7 @@ private:
// locked & unlocked balance of given or current subaddress account
uint64_t balance(uint32_t subaddr_index_major, bool strict) const;
uint64_t unlocked_balance(uint32_t subaddr_index_major, bool strict, uint64_t *blocks_to_unlock = NULL, uint64_t *time_to_unlock = NULL);
@@ -165,3 +182,6 @@ index 74bb867c1..40997cdbb 100644
// locked & unlocked balance per subaddress of given or current subaddress account
std::map<uint32_t, uint64_t> balance_per_subaddress(uint32_t subaddr_index_major, bool strict) const;
std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> 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
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 <cyjan@mrcyjanek.net>
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<cryptonote::tx_destination_entry
+@@ -10487,7 +10510,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
LOG_PRINT_L2("transfer_selected_rct done");
}
@@ -786,7 +786,7 @@ index 3477e084f..c3376f7e0 100644
{
std::vector<size_t> picks;
float current_output_relatdness = 1.0f;
-@@ -10506,6 +10529,9 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
+@@ -10498,6 +10521,9 @@ std::vector<size_t> 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<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
+@@ -10518,6 +10544,9 @@ std::vector<size_t> 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<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
+@@ -10529,6 +10558,9 @@ std::vector<size_t> 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::pending_tx> wallet2::create_transactions_2(std::vector<cryp
+@@ -11309,6 +11341,9 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
for (size_t i = 0; i < m_transfers.size(); ++i)
{
const transfer_details& td = m_transfers[i];
@@ -835,7 +835,7 @@ index 3477e084f..c3376f7e0 100644
if (m_ignore_fractional_outputs && td.amount() < fractional_threshold)
{
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is below fractional threshold " << print_money(fractional_threshold));
-@@ -11401,7 +11436,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
+@@ -11393,7 +11428,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
// will get us a known fee.
uint64_t estimated_fee = estimate_fee(use_per_byte_fee, use_rct, 2, fake_outs_count, 2, extra.size(), bulletproof, clsag, bulletproof_plus, use_view_tags, base_fee, fee_quantization_mask);
total_needed_money = needed_money + (subtract_fee_from_outputs.size() ? 0 : estimated_fee);
@@ -844,7 +844,7 @@ index 3477e084f..c3376f7e0 100644
if (!preferred_inputs.empty())
{
string s;
-@@ -11882,7 +11917,7 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, c
+@@ -11874,7 +11909,7 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, c
return true;
}
@@ -853,7 +853,7 @@ index 3477e084f..c3376f7e0 100644
{
std::vector<size_t> unused_transfers_indices;
std::vector<size_t> unused_dust_indices;
-@@ -11911,6 +11946,9 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
+@@ -11903,6 +11938,9 @@ std::vector<wallet2::pending_tx> 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<wallet2::pending_tx> 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<uint8_t>& extra);
std::vector<wallet2::pending_tx> create_transactions_from(const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, std::vector<size_t> unused_transfers_indices, std::vector<size_t> unused_dust_indices, const size_t fake_outs_count, const uint64_t unlock_time, uint32_t priority, const std::vector<uint8_t>& extra);
bool sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, const std::vector<cryptonote::tx_destination_entry>& 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<uint64_t> 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
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 <cyjan@mrcyjanek.net>
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
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 <you@example.com>
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
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 <cyjan@mrcyjanek.net>
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
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 <cyjan@mrcyjanek.net>
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
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 <cyjan@mrcyjanek.net>
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
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 <cyjan@mrcyjanek.net>
-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<Wallet::Device>(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<WalletImpl*>(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::keys_file_data> wallet2::get_keys_file_data(const epee:
+@@ -4712,6 +4729,9 @@ boost::optional<wallet2::keys_file_data> 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<rapidjson::StringBuffer> 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<size_t> select_available_outputs_from_histogram(uint64_t count, bool atleast, bool unlocked, bool allow_rct);
std::vector<size_t> select_available_outputs(const std::function<bool(const transfer_details &td)> &f);
std::vector<size_t> 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<std::string> &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<crypto::public_key> 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
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 <cyjan@mrcyjanek.net>
-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 <justinberman@protonmail.com>
+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<std::string> &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 <off|reuse-wallet-password|custom-background-password>\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 <device_name[:device_spec]>\n "
+@@ -3909,6 +4019,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &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<std::string> &args)
+@@ -3928,6 +4039,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &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<std::string> &args)
+@@ -3981,6 +4093,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &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<tools::password_container> 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<epee::wipeable_string> simple_wallet::open_wallet(const boost::p
+@@ -5240,6 +5356,8 @@ boost::optional<epee::wipeable_string> 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<std::string>& args)
+@@ -6319,6 +6441,7 @@ bool simple_wallet::show_blockchain_height(const std::vector<std::string>& args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::rescan_spent(const std::vector<std::string> &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<std:
+@@ -6660,6 +6808,7 @@ bool simple_wallet::on_command(bool (simple_wallet::*cmd)(const std::vector<std:
bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::string> &args_, bool called_by_mms)
{
// "transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>]"
@@ -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<std::stri
+@@ -7133,6 +7282,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
//----------------------------------------------------------------------------------------------------
bool simple_wallet::transfer(const std::vector<std::string> &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<std::string> &args_)
+@@ -7144,6 +7294,7 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::locked_transfer(const std::vector<std::string> &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<std::string> &args_)
+@@ -7155,6 +7306,7 @@ bool simple_wallet::locked_transfer(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::locked_sweep_all(const std::vector<std::string> &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<std::string> &args_)
+@@ -7167,6 +7319,7 @@ bool simple_wallet::locked_sweep_all(const std::vector<std::string> &args_)
bool simple_wallet::sweep_unmixable(const std::vector<std::string> &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<std::string> &args_)
+@@ -7274,6 +7427,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, const std::vector<std::string> &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<std::string> &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<std::string> &args_)
+@@ -7828,12 +7983,14 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sweep_all(const std::vector<std::string> &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<std::string> &args_)
+@@ -7854,6 +8011,7 @@ bool simple_wallet::sweep_account(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sweep_below(const std::vector<std::string> &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<std::string> &args_)
+@@ -7872,6 +8030,7 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::donate(const std::vector<std::string> &args_)
{
@@ -480,7 +501,7 @@ index b437092a4..754f088d6 100644
std::vector<std::string> local_args = args_;
if(local_args.empty() || local_args.size() > 5)
{
-@@ -7933,6 +8090,7 @@ bool simple_wallet::donate(const std::vector<std::string> &args_)
+@@ -7933,6 +8092,7 @@ bool simple_wallet::donate(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes, const std::function<const tools::wallet2::tx_construction_data&(size_t)> &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<std::string> &args_)
+@@ -8113,6 +8273,7 @@ bool simple_wallet::sign_transfer(const std::vector<std::string> &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<crypto::sec
+@@ -8220,6 +8381,8 @@ std::string get_tx_key_stream(crypto::secret_key tx_key, std::vector<crypto::sec
bool simple_wallet::get_tx_key(const std::vector<std::string> &args_)
{
@@ -507,7 +526,7 @@ index b437092a4..754f088d6 100644
std::vector<std::string> 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<std::string> &args_)
+@@ -8260,6 +8423,8 @@ bool simple_wallet::get_tx_key(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::set_tx_key(const std::vector<std::string> &args_)
{
@@ -516,7 +535,7 @@ index b437092a4..754f088d6 100644
std::vector<std::string> 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<std::string> &args_)
+@@ -8336,6 +8501,8 @@ bool simple_wallet::set_tx_key(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::get_tx_proof(const std::vector<std::string> &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<std::string> &args)
+@@ -8542,6 +8709,7 @@ bool simple_wallet::check_tx_proof(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::get_spend_proof(const std::vector<std::string> &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<std::string> &args)
+@@ -8626,6 +8794,7 @@ bool simple_wallet::check_spend_proof(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::get_reserve_proof(const std::vector<std::string> &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<std::string> &args_)
+@@ -9312,6 +9481,8 @@ bool simple_wallet::unspent_outputs(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::rescan_blockchain(const std::vector<std::string> &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<std::string> &args/* = std::vector
+@@ -9622,6 +9793,7 @@ bool simple_wallet::account(const std::vector<std::string> &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<std::string> &args/* = std::vector
+@@ -9652,6 +9824,7 @@ bool simple_wallet::account(const std::vector<std::string> &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<std::string> &args/* = std::vector
+@@ -9673,6 +9846,7 @@ bool simple_wallet::account(const std::vector<std::string> &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<uint32_t> account_indices;
for (size_t i = 1; i < local_args.size(); ++i)
-@@ -9697,6 +9869,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
+@@ -9697,6 +9871,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
}
else if (command == "untag" && local_args.size() >= 1)
{
@@ -582,7 +601,7 @@ index b437092a4..754f088d6 100644
std::set<uint32_t> account_indices;
for (size_t i = 0; i < local_args.size(); ++i)
{
-@@ -9720,6 +9893,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
+@@ -9720,6 +9895,7 @@ bool simple_wallet::account(const std::vector<std::string> &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<std::string> &args/* = std::
+@@ -9837,6 +10013,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &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<std::string> &args/* = std::
+@@ -9849,6 +10026,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &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<std::string> &args/* = std::
+@@ -9874,6 +10052,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &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<std::string> &args/* = std::
+@@ -9892,6 +10071,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &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<std::string> &arg
+@@ -10038,6 +10218,8 @@ bool simple_wallet::print_integrated_address(const std::vector<std::string> &arg
//----------------------------------------------------------------------------------------------------
bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
@@ -631,7 +650,7 @@ index b437092a4..754f088d6 100644
if (args.size() == 0)
{
}
-@@ -10098,6 +10278,8 @@ bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::v
+@@ -10098,6 +10280,8 @@ bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::v
//----------------------------------------------------------------------------------------------------
bool simple_wallet::set_tx_note(const std::vector<std::string> &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<std::string> &args)
+@@ -10126,6 +10310,8 @@ bool simple_wallet::set_tx_note(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::get_tx_note(const std::vector<std::string> &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<std::string> &args)
+@@ -10151,6 +10337,8 @@ bool simple_wallet::get_tx_note(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::set_description(const std::vector<std::string> &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<std::string> &args)
+@@ -10167,6 +10355,8 @@ bool simple_wallet::set_description(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::get_description(const std::vector<std::string> &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<std::string> &args)
+@@ -10225,6 +10415,8 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &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<std::string> &args)
+@@ -10236,6 +10428,7 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sign(const std::vector<std::string> &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<std::string> &args_)
+@@ -10343,6 +10536,7 @@ bool simple_wallet::export_key_images(const std::vector<std::string> &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<std::string> &args)
+@@ -10396,6 +10590,7 @@ bool simple_wallet::import_key_images(const std::vector<std::string> &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<std::string> &args_)
+@@ -10504,6 +10699,7 @@ bool simple_wallet::export_outputs(const std::vector<std::string> &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<std::string> &args)
+@@ -10553,6 +10749,7 @@ bool simple_wallet::import_outputs(const std::vector<std::string> &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<std::string> &args = std::vector<std::string>());
bool set_inactivity_lock_timeout(const std::vector<std::string> &args = std::vector<std::string>());
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<boost::mutex> 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<boost::mutex> guarg(m_refreshMutex2);
+ do try {
+ LOG_PRINT_L3(__FUNCTION__ << ": doRefresh, rescan = "<<rescan);
+- if(rescan)
+- m_wallet->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<std::string> &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<uint64_t> &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<std::string> &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<std::string> &background_cache_password = optional<std::string>()) 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<std::pair<std::string, uint64_t>> &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<TransactionHistoryImpl> m_history;
std::unique_ptr<Wallet2CallbackImpl> 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<std::string> &txids) = 0;
+@@ -1094,6 +1100,41 @@ struct Wallet
+ virtual std::string printScannedPoolTxs() = 0;
+ virtual bool importTransaction(const std::string &txid, std::vector<uint64_t> &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<too
+@@ -1116,7 +1118,7 @@ wallet_keys_unlocker::wallet_keys_unlocker(wallet2 &w, const boost::optional<too
boost::lock_guard<boost::mutex> 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<crypto::hash> &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<epee::wipeable_string> 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<unsigned int>(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<std::tuple<cryptonote::transaction, crypto::hash, bool>> &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<std::pair<uint64_t, uint64_
+@@ -4421,8 +4512,12 @@ void wallet2::handle_reorg(uint64_t height, std::map<std::pair<uint64_t, uint64_
+ // C
+ THROW_WALLET_EXCEPTION_IF(height < m_blockchain.offset() && m_blockchain.size() > 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<wallet2::keys_file_data> 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::keys_file_data> 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::keys_file_data> wallet2::get_keys_file_data(const epee:
+@@ -4669,6 +4803,9 @@ boost::optional<wallet2::keys_file_data> 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::keys_file_data> 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::keys_file_data> 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<const char*>(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<size_t>::max());
++ r = load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits<size_t>::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<wallet2> 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<size_t>::max());
-+ r = load_from_file(m_wallet_file, cache_file_buf, std::numeric_limits<size_t>::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<wallet2::cache_file_data> 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::cache_file_data> wallet2::get_cache_file_data()
-@@ -6964,7 +7400,7 @@ boost::optional<wallet2::cache_file_data> wallet2::get_cache_file_data()
+@@ -6964,7 +7392,7 @@ boost::optional<wallet2::cache_file_data> wallet2::get_cache_file_data()
std::string cipher;
cipher.resize(cache_file_data.get().cache_data.size());
cache_file_data.get().iv = crypto::rand<crypto::chacha_iv>();
@@ -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<std::vector<tools::wallet2::get_outs_entry>> &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<crypto::public_key> &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<std::pair<crypto::hash, background_synced_tx>> sorted_bgs_cache(background_sync_data.txs.begin(), background_sync_data.txs.end());
++ std::vector<std::pair<crypto::hash, background_synced_tx_t>> 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<crypto::hash, background_synced_tx>& l, const std::pair<crypto::hash, background_synced_tx>& r)
++ [](const std::pair<crypto::hash, background_synced_tx_t>& l, const std::pair<crypto::hash, background_synced_tx_t>& 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<wallet2> 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<crypto::hash, background_synced_tx> txs;
++ bool first_refresh_done = false;
++ uint64_t start_height = 0;
++ serializable_unordered_map<crypto::hash, background_synced_tx_t> 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<crypto::secret_key> &additional_tx_keys) const;
- void set_tx_key(const crypto::hash &txid, const crypto::secret_key &tx_key, const std::vector<crypto::secret_key> &additional_tx_keys, const boost::optional<cryptonote::account_public_address> &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<uint64_t> &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<std::pair<uint64_t, uint64_t>, 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> &tx_cache_data, size_t tx_cache_data_offset, std::map<std::pair<uint64_t, uint64_t>, size_t> *output_tracker_cache = NULL);
-@@ -1796,6 +1888,7 @@ private:
+@@ -1796,6 +1888,15 @@ private:
void get_short_chain_history(std::list<crypto::hash>& 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<crypto::hash> &short_chain_history, std::vector<cryptonote::block_complete_entry> &blocks, std::vector<cryptonote::COMMAND_RPC_GET_BLOCKS_FAST::block_output_indices> &o_indices, uint64_t &current_height);
void pull_hashes(uint64_t start_height, uint64_t& blocks_start_height, const std::list<crypto::hash> &short_chain_history, std::vector<crypto::hash> &hashes);
void fast_refresh(uint64_t stop_height, uint64_t &blocks_start_height, std::list<crypto::hash> &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<uint64_t> &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<tools::file_locker> 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<wallet_keys_unlocker> 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 <class Archive>
-+ 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
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 <cyjan@mrcyjanek.net>
-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<std::pair<std::string, uint64_t>> &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<crypto::key_image>& 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<uint32_t, uint64_t> wallet2::balance_per_subaddress(uint32_t index_major, bool strict) const
{
std::map<uint32_t, uint64_t> amount_per_subaddr;
-@@ -7895,9 +7924,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin
+@@ -8282,9 +8301,7 @@ bool wallet2::sign_tx(unsigned_tx_set &exported_txs, std::vector<wallet2::pendin
crypto::key_derivation derivation;
std::vector<crypto::key_derivation> additional_derivations;
@@ -151,7 +134,7 @@ index 618c43cee..3477e084f 100644
std::vector<crypto::public_key> additional_tx_pub_keys;
for (const crypto::secret_key &skey: txs[n].additional_tx_keys)
{
-@@ -11295,7 +11322,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
+@@ -11692,7 +11709,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
MDEBUG("Ignoring output " << i << " of amount " << print_money(td.amount()) << " which is below fractional threshold " << print_money(fractional_threshold));
continue;
}
@@ -160,7 +143,7 @@ index 618c43cee..3477e084f 100644
{
if (td.amount() > m_ignore_outputs_above || td.amount() < m_ignore_outputs_below)
{
-@@ -11345,8 +11372,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
+@@ -11742,8 +11759,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
LOG_PRINT_L2("Starting with " << num_nondust_outputs << " non-dust outputs and " << num_dust_outputs << " dust outputs");
@@ -171,10 +154,10 @@ index 618c43cee..3477e084f 100644
// if empty, put dummy entry so that the front can be referenced later in the loop
if (unused_dust_indices_per_subaddr.empty())
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
-index bfe3a4f19..406acac2b 100644
+index 2f2664f8e..51dbb5b89 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
-@@ -1172,6 +1172,7 @@ private:
+@@ -1173,6 +1173,7 @@ private:
// locked & unlocked balance of given or current subaddress account
uint64_t balance(uint32_t subaddr_index_major, bool strict) const;
uint64_t unlocked_balance(uint32_t subaddr_index_major, bool strict, uint64_t *blocks_to_unlock = NULL, uint64_t *time_to_unlock = NULL);
@@ -182,3 +165,6 @@ index bfe3a4f19..406acac2b 100644
// locked & unlocked balance per subaddress of given or current subaddress account
std::map<uint32_t, uint64_t> balance_per_subaddress(uint32_t subaddr_index_major, bool strict) const;
std::map<uint32_t, std::pair<uint64_t, std::pair<uint64_t, uint64_t>>> 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
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 <cyjan@mrcyjanek.net>
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<CoinsInfo*> 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<stri
@@ -136,7 +136,7 @@ index 63ed26a11..3bbc60d74 100644
pendingTxPostProcess(transaction);
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
-index c2fa3d95b..99616b025 100644
+index 39b942ef4..678f9b6b9 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -352,9 +352,12 @@ struct Coins
@@ -153,10 +153,10 @@ index c2fa3d95b..99616b025 100644
struct SubaddressRow {
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
-index 00d9c133e..ae0305d28 100644
+index f996863ff..c53b1de67 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
-@@ -2092,11 +2092,21 @@ bool wallet2::frozen(const multisig_tx_set& txs) const
+@@ -2094,11 +2094,21 @@ bool wallet2::frozen(const multisig_tx_set& txs) const
return false;
}
//----------------------------------------------------------------------------------------------------
@@ -178,7 +178,7 @@ index 00d9c133e..ae0305d28 100644
void wallet2::thaw(const crypto::key_image &ki)
{
thaw(get_transfer_details(ki));
-@@ -2107,6 +2117,18 @@ bool wallet2::frozen(const crypto::key_image &ki) const
+@@ -2109,6 +2119,18 @@ bool wallet2::frozen(const crypto::key_image &ki) const
return frozen(get_transfer_details(ki));
}
//----------------------------------------------------------------------------------------------------
@@ -198,10 +198,10 @@ index 00d9c133e..ae0305d28 100644
{
for (size_t idx = 0; idx < m_transfers.size(); ++idx)
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
-index 40997cdbb..6fa955681 100644
+index 51dbb5b89..5e27e46cf 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
-@@ -1562,6 +1562,8 @@ private:
+@@ -1563,6 +1563,8 @@ 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;
@@ -210,7 +210,7 @@ index 40997cdbb..6fa955681 100644
uint8_t get_current_hard_fork();
void get_hard_fork_info(uint8_t version, uint64_t &earliest_height);
-@@ -1792,7 +1794,9 @@ private:
+@@ -1793,7 +1795,9 @@ private:
void freeze(size_t idx);
void thaw(size_t idx);
bool frozen(size_t idx) const;
@@ -221,5 +221,5 @@ index 40997cdbb..6fa955681 100644
bool frozen(const crypto::key_image &ki) const;
bool frozen(const transfer_details &td) const;
--
-2.39.2
+2.44.0
diff --git a/patches/wownero/0005-fix-build.patch b/patches/wownero/0006-fix-build.patch
index cd6c599..2214dfb 100644
--- a/patches/wownero/0005-fix-build.patch
+++ b/patches/wownero/0006-fix-build.patch
@@ -1,7 +1,7 @@
-From e255cea2987df8b61dff62657480aa48fcb2ff39 Mon Sep 17 00:00:00 2001
+From 60bfb0146f7756fe339f9d3744df2bebdf628dfb Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
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
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 <you@example.com>
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
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 <cyjan@mrcyjanek.net>
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
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 <cyjan@mrcyjanek.net>
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