summaryrefslogtreecommitdiff
path: root/patches
diff options
context:
space:
mode:
Diffstat (limited to 'patches')
-rw-r--r--patches/monero/0001-wallet-background-sync-with-just-the-view-key.patch (renamed from patches/monero/0002-wallet-background-sync-with-just-the-view-key.patch)425
-rw-r--r--patches/monero/0002-fix-missing-___clear_cache-when-targetting-iOS.patch (renamed from patches/monero/0008-fix-missing-___clear_cache-when-targetting-iOS.patch)23
-rw-r--r--patches/monero/0003-airgap.patch195
-rw-r--r--patches/monero/0003-store-crash-fix.patch (renamed from patches/wownero/0014-store-crash-fix.patch)57
-rw-r--r--patches/monero/0004-uint64_t-missing-definition-fix.patch (renamed from patches/wownero/0015-uint64_t-missing-definition-fix.patch)8
-rw-r--r--patches/monero/0005-fix-build-issues.patch137
-rw-r--r--patches/monero/0005-use-proper-error-handling-in-get_seed.patch (renamed from patches/wownero/0013-use-proper-error-handling-in-get_seed.patch)29
-rw-r--r--patches/monero/0006-UR-functions.patch (renamed from patches/monero/0012-WIP-UR-functions.patch)285
-rw-r--r--patches/monero/0006-macos-build-fix.patch114
-rw-r--r--patches/monero/0007-add-dummy-device-for-ledger.patch604
-rw-r--r--patches/monero/0007-fix-make-debug-test-target.patch39
-rw-r--r--patches/monero/0008-polyseed.patch (renamed from patches/monero/0001-polyseed.patch)239
-rw-r--r--patches/monero/0009-coin-control.patch979
-rw-r--r--patches/monero/0010-Add-hex-encoding-and-tx-key-getter-for-PendingTransc.patch18
-rw-r--r--patches/monero/0011-Add-recoverDeterministicWalletFromSpendKey.patch153
-rw-r--r--patches/monero/0012-add-monero-submodule-support.patch65
-rw-r--r--patches/monero/0013-android-ndk-version-bump.patch120
-rw-r--r--patches/monero/0013-fix-iOS-depends-build.patch104
-rw-r--r--patches/monero/0014-include-locale-only-when-targeting-WIN32.patch43
-rw-r--r--patches/monero/0014-rename-arm-armv7a.patch94
-rw-r--r--patches/monero/0017-added-deps.patch29
-rw-r--r--patches/monero/0018-fix-coin-control-patch.patch30
-rw-r--r--patches/monero/0019-fix-for-coin-control-patch.patch97
-rw-r--r--patches/monero/0020-catch-exception-in-queryWalletDevice.patch35
-rw-r--r--patches/monero/README.md43
-rw-r--r--patches/wownero/0001-Fix-wallet_api-compilation-target-https-git.wownero..patch31
-rw-r--r--patches/wownero/0001-wallet-background-sync-with-just-the-view-key.patch (renamed from patches/wownero/0003-wallet-background-sync-with-just-the-view-key.patch)619
-rw-r--r--patches/wownero/0002-fix-missing-___clear_cache-when-targetting-iOS.patch19
-rw-r--r--patches/wownero/0003-fix-is_trivially_copyable.patch32
-rw-r--r--patches/wownero/0004-airgap.patch170
-rw-r--r--patches/wownero/0004-store-crash-fix.patch (renamed from patches/monero/0011-store-crash-fix.patch)44
-rw-r--r--patches/wownero/0005-coin-control.patch225
-rw-r--r--patches/wownero/0005-uint64_t-missing-definition-fix.patch (renamed from patches/monero/0016-uint64_t-missing-definition-fix.patch)6
-rw-r--r--patches/wownero/0006-fix-build.patch137
-rw-r--r--patches/wownero/0006-use-proper-error-handling-in-get_seed.patch (renamed from patches/monero/0015-use-proper-error-handling-in-get_seed.patch)29
-rw-r--r--patches/wownero/0007-UR-functions.patch1036
-rw-r--r--patches/wownero/0007-macos-build-fix.patch114
-rw-r--r--patches/wownero/0008-FIX-wallet-listener-crashing.patch58
-rw-r--r--patches/wownero/0008-add-dummy-device-for-ledger.patch (renamed from patches/monero/0016-add-dummy-device-for-ledger.patch)128
-rw-r--r--patches/wownero/0009-fix-missing-___clear_cache-when-targetting-iOS.patch33
-rw-r--r--patches/wownero/0009-polyseed.patch (renamed from patches/wownero/0002-polyseed.patch)473
-rw-r--r--patches/wownero/0010-build-wownero-seed.patch613
-rw-r--r--patches/wownero/0010-coin-control.patch (renamed from patches/monero/0004-coin-control.patch)187
-rw-r--r--patches/wownero/0011-Add-hex-encoding-and-tx-key-getter-for-PendingTransc.patch68
-rw-r--r--patches/wownero/0011-android-ndk-version-bump.patch120
-rw-r--r--patches/wownero/0012-Add-recoverDeterministicWalletFromSpendKey.patch (renamed from patches/monero/0009-Add-recoverDeterministicWalletFromSpendKey.patch)18
-rw-r--r--patches/wownero/0012-rename-arm-armv7a.patch94
-rw-r--r--patches/wownero/0013-add-monero-submodule-support.patch65
-rw-r--r--patches/wownero/0014-fix-iOS-depends-build.patch104
-rw-r--r--patches/wownero/0015-include-locale-only-when-targeting-WIN32.patch43
-rw-r--r--patches/wownero/README.md35
51 files changed, 4792 insertions, 3674 deletions
diff --git a/patches/monero/0002-wallet-background-sync-with-just-the-view-key.patch b/patches/monero/0001-wallet-background-sync-with-just-the-view-key.patch
index 16fe77f..849c8be 100644
--- a/patches/monero/0002-wallet-background-sync-with-just-the-view-key.patch
+++ b/patches/monero/0001-wallet-background-sync-with-just-the-view-key.patch
@@ -1,7 +1,7 @@
-From 56fed429a25773c760b8490b3e0fb908c832e6e5 Mon Sep 17 00:00:00 2001
+From 0efd53a750d0827a500b036dc30ab190689e7e13 Mon Sep 17 00:00:00 2001
From: j-berman <justinberman@protonmail.com>
Date: Thu, 13 Oct 2022 18:33:33 -0700
-Subject: [PATCH 02/16] wallet: background sync with just the view key
+Subject: [PATCH 01/14] 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
@@ -30,12 +30,12 @@ cache.
src/cryptonote_basic/account.cpp | 11 +
src/cryptonote_basic/account.h | 1 +
src/cryptonote_config.h | 2 +
- src/simplewallet/simplewallet.cpp | 203 +++-
+ src/simplewallet/simplewallet.cpp | 204 +++-
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.cpp | 1030 ++++++++++++++++--
src/wallet/wallet2.h | 156 ++-
src/wallet/wallet_errors.h | 39 +
src/wallet/wallet_rpc_server.cpp | 162 +++
@@ -47,14 +47,14 @@ cache.
tests/functional_tests/wallet.py | 43 +-
tests/unit_tests/wipeable_string.cpp | 12 +
utils/python-rpc/framework/wallet.py | 42 +
- 20 files changed, 2335 insertions(+), 130 deletions(-)
+ 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
+index 2ac455f..4e87d44 100644
--- a/src/cryptonote_basic/account.cpp
+++ b/src/cryptonote_basic/account.cpp
-@@ -158,6 +158,17 @@ DISABLE_VS_WARNINGS(4244 4345)
- m_keys.m_passphrase.wipe();
+@@ -152,6 +152,17 @@ DISABLE_VS_WARNINGS(4244 4345)
+ m_keys.m_multisig_keys.clear();
}
//-----------------------------------------------------------------
+ void account_base::set_spend_key(const crypto::secret_key& spend_secret_key)
@@ -72,10 +72,10 @@ index 4931c3740..2d556f285 100644
{
crypto::secret_key first = generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, recovery_key, recover);
diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h
-index 0099ebfe7..1f76febce 100644
+index 2ee9545..93d1d28 100644
--- a/src/cryptonote_basic/account.h
+++ b/src/cryptonote_basic/account.h
-@@ -101,6 +101,7 @@ namespace cryptonote
+@@ -95,6 +95,7 @@ namespace cryptonote
bool store(const std::string& file_path);
void forget_spend_key();
@@ -84,10 +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..3af3a63a1 100644
+index 61146a1..f9e6a6c 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
-@@ -243,6 +243,8 @@ namespace config
+@@ -241,6 +241,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;
@@ -97,7 +97,7 @@ index 8e1a07110..3af3a63a1 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 b9e30f9d9..f8ed6659c 100644
+index b9e30f9..2c51337 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -155,6 +155,17 @@ typedef cryptonote::simple_wallet sw;
@@ -229,7 +229,7 @@ index b9e30f9d9..f8ed6659c 100644
if (args.empty())
{
size_t ntd = m_wallet->get_num_transfer_details();
-@@ -3005,6 +3062,56 @@ bool simple_wallet::set_track_uses(const std::vector<std::string> &args/* = std:
+@@ -3005,6 +3062,57 @@ bool simple_wallet::set_track_uses(const std::vector<std::string> &args/* = std:
return true;
}
@@ -251,42 +251,43 @@ index b9e30f9d9..f8ed6659c 100644
+ return true;
+ }
+
-+ const auto pwd_container = get_and_verify_password();
-+ if (pwd_container)
++ tools::wallet2::BackgroundSyncType background_sync_type;
++ if (!parse_background_sync_type(args[1], background_sync_type))
+ {
-+ tools::wallet2::BackgroundSyncType background_sync_type;
-+ if (!parse_background_sync_type(args[1], background_sync_type))
-+ {
-+ fail_msg_writer() << tr("invalid option");
-+ return true;
-+ }
++ fail_msg_writer() << tr("invalid option");
++ return true;
++ }
+
-+ try
-+ {
-+ boost::optional<epee::wipeable_string> background_cache_password = boost::none;
-+ if (background_sync_type == tools::wallet2::BackgroundSyncCustomPassword)
-+ {
-+ const auto background_pwd_container = background_sync_cache_password_prompter(true);
-+ if (!background_pwd_container)
-+ return true;
-+ background_cache_password = background_pwd_container->password();
-+ }
++ const auto pwd_container = get_and_verify_password();
++ if (!pwd_container)
++ return true;
+
-+ LOCK_IDLE_SCOPE();
-+ m_wallet->setup_background_sync(background_sync_type, pwd_container->password(), background_cache_password);
-+ }
-+ catch (const std::exception &e)
++ try
++ {
++ boost::optional<epee::wipeable_string> background_cache_password = boost::none;
++ if (background_sync_type == tools::wallet2::BackgroundSyncCustomPassword)
+ {
-+ fail_msg_writer() << tr("Error setting background sync type: ") << e.what();
++ const auto background_pwd_container = background_sync_cache_password_prompter(true);
++ if (!background_pwd_container)
++ return true;
++ background_cache_password = background_pwd_container->password();
+ }
++
++ LOCK_IDLE_SCOPE();
++ m_wallet->setup_background_sync(background_sync_type, pwd_container->password(), background_cache_password);
+ }
++ catch (const std::exception &e)
++ {
++ fail_msg_writer() << tr("Error setting background sync type: ") << e.what();
++ }
++
+ return true;
+}
+
bool simple_wallet::set_show_wallet_name_when_locked(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
const auto pwd_container = get_and_verify_password();
-@@ -3237,6 +3344,7 @@ bool simple_wallet::apropos(const std::vector<std::string> &args)
+@@ -3237,6 +3345,7 @@ bool simple_wallet::apropos(const std::vector<std::string> &args)
bool simple_wallet::scan_tx(const std::vector<std::string> &args)
{
@@ -294,7 +295,7 @@ index b9e30f9d9..f8ed6659c 100644
if (args.empty())
{
PRINT_USAGE(USAGE_SCAN_TX);
-@@ -3458,6 +3566,8 @@ simple_wallet::simple_wallet()
+@@ -3458,6 +3567,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 "
@@ -303,7 +304,7 @@ index b9e30f9d9..f8ed6659c 100644
"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 monero.\n "
"device-name <device_name[:device_spec]>\n "
-@@ -3876,6 +3986,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
+@@ -3876,6 +3987,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();
@@ -311,7 +312,7 @@ index b9e30f9d9..f8ed6659c 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");
-@@ -3894,6 +4005,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
+@@ -3894,6 +4006,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
}
else
{
@@ -319,7 +320,7 @@ index b9e30f9d9..f8ed6659c 100644
#define CHECK_SIMPLE_VARIABLE(name, f, help) do \
if (args[0] == name) { \
-@@ -3947,6 +4059,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
+@@ -3947,6 +4060,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"));
@@ -327,7 +328,7 @@ index b9e30f9d9..f8ed6659c 100644
CHECK_SIMPLE_VARIABLE("show-wallet-name-when-locked", set_show_wallet_name_when_locked, tr("1 or 0"));
CHECK_SIMPLE_VARIABLE("inactivity-lock-timeout", set_inactivity_lock_timeout, tr("unsigned integer (seconds, 0 to disable)"));
CHECK_SIMPLE_VARIABLE("setup-background-mining", set_setup_background_mining, tr("1/yes or 0/no"));
-@@ -4900,7 +5013,10 @@ std::string simple_wallet::get_mnemonic_language()
+@@ -4900,7 +5014,10 @@ std::string simple_wallet::get_mnemonic_language()
//----------------------------------------------------------------------------------------------------
boost::optional<tools::password_container> simple_wallet::get_and_verify_password() const
{
@@ -339,7 +340,7 @@ index b9e30f9d9..f8ed6659c 100644
if (!pwd_container)
return boost::none;
-@@ -5203,6 +5319,8 @@ boost::optional<epee::wipeable_string> simple_wallet::open_wallet(const boost::p
+@@ -5203,6 +5320,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();
@@ -348,7 +349,7 @@ index b9e30f9d9..f8ed6659c 100644
else
prefix = tr("Opened wallet");
message_writer(console_color_white, true) <<
-@@ -5411,6 +5529,10 @@ void simple_wallet::stop_background_mining()
+@@ -5411,6 +5530,10 @@ void simple_wallet::stop_background_mining()
//----------------------------------------------------------------------------------------------------
void simple_wallet::check_background_mining(const epee::wipeable_string &password)
{
@@ -359,7 +360,7 @@ index b9e30f9d9..f8ed6659c 100644
tools::wallet2::BackgroundMiningSetupType setup = m_wallet->setup_background_mining();
if (setup == tools::wallet2::BackgroundMiningNo)
{
-@@ -6275,6 +6397,7 @@ bool simple_wallet::show_blockchain_height(const std::vector<std::string>& args)
+@@ -6275,6 +6398,7 @@ bool simple_wallet::show_blockchain_height(const std::vector<std::string>& args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::rescan_spent(const std::vector<std::string> &args)
{
@@ -367,7 +368,7 @@ index b9e30f9d9..f8ed6659c 100644
if (!m_wallet->is_trusted_daemon())
{
fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon");
-@@ -6532,10 +6655,27 @@ void simple_wallet::check_for_inactivity_lock(bool user)
+@@ -6532,10 +6656,27 @@ void simple_wallet::check_for_inactivity_lock(bool user)
" || ||" << std::endl <<
"" << std::endl;
}
@@ -396,7 +397,7 @@ index b9e30f9d9..f8ed6659c 100644
const bool show_wallet_name = m_wallet->show_wallet_name_when_locked();
if (show_wallet_name)
-@@ -6548,8 +6688,16 @@ void simple_wallet::check_for_inactivity_lock(bool user)
+@@ -6548,8 +6689,16 @@ void simple_wallet::check_for_inactivity_lock(bool user)
}
try
{
@@ -414,7 +415,7 @@ index b9e30f9d9..f8ed6659c 100644
}
catch (...) { /* do nothing, just let the loop loop */ }
}
-@@ -6576,6 +6724,7 @@ bool simple_wallet::on_command(bool (simple_wallet::*cmd)(const std::vector<std:
+@@ -6576,6 +6725,7 @@ bool simple_wallet::on_command(bool (simple_wallet::*cmd)(const std::vector<std:
bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool called_by_mms)
{
// "transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>]"
@@ -422,7 +423,7 @@ index b9e30f9d9..f8ed6659c 100644
if (!try_connect_to_daemon())
return false;
-@@ -7004,6 +7153,7 @@ bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool ca
+@@ -7004,6 +7154,7 @@ bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool ca
//----------------------------------------------------------------------------------------------------
bool simple_wallet::transfer(const std::vector<std::string> &args_)
{
@@ -430,7 +431,7 @@ index b9e30f9d9..f8ed6659c 100644
if (args_.size() < 1)
{
PRINT_USAGE(USAGE_TRANSFER);
-@@ -7016,6 +7166,7 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
+@@ -7016,6 +7167,7 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
{
@@ -438,7 +439,7 @@ index b9e30f9d9..f8ed6659c 100644
if (!try_connect_to_daemon())
return true;
-@@ -7123,6 +7274,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
+@@ -7123,6 +7275,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sweep_main(uint32_t account, uint64_t below, const std::vector<std::string> &args_)
{
@@ -446,7 +447,7 @@ index b9e30f9d9..f8ed6659c 100644
auto print_usage = [this, account, below]()
{
if (below)
-@@ -7404,6 +7556,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, const std::vect
+@@ -7404,6 +7557,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, const std::vect
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
{
@@ -454,7 +455,7 @@ index b9e30f9d9..f8ed6659c 100644
if (!try_connect_to_daemon())
return true;
-@@ -7642,12 +7795,14 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
+@@ -7642,12 +7796,14 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sweep_all(const std::vector<std::string> &args_)
{
@@ -469,7 +470,7 @@ index b9e30f9d9..f8ed6659c 100644
auto local_args = args_;
if (local_args.empty())
{
-@@ -7668,6 +7823,7 @@ bool simple_wallet::sweep_account(const std::vector<std::string> &args_)
+@@ -7668,6 +7824,7 @@ bool simple_wallet::sweep_account(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sweep_below(const std::vector<std::string> &args_)
{
@@ -477,7 +478,7 @@ index b9e30f9d9..f8ed6659c 100644
uint64_t below = 0;
if (args_.size() < 1)
{
-@@ -7686,6 +7842,7 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_)
+@@ -7686,6 +7843,7 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::donate(const std::vector<std::string> &args_)
{
@@ -485,7 +486,7 @@ index b9e30f9d9..f8ed6659c 100644
std::vector<std::string> local_args = args_;
if(local_args.empty() || local_args.size() > 5)
{
-@@ -7747,6 +7904,7 @@ bool simple_wallet::donate(const std::vector<std::string> &args_)
+@@ -7747,6 +7905,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)
{
@@ -493,7 +494,7 @@ index b9e30f9d9..f8ed6659c 100644
// gather info to ask the user
uint64_t amount = 0, amount_to_dests = 0, change = 0;
size_t min_ring_size = ~0;
-@@ -7927,6 +8085,7 @@ bool simple_wallet::sign_transfer(const std::vector<std::string> &args_)
+@@ -7927,6 +8086,7 @@ bool simple_wallet::sign_transfer(const std::vector<std::string> &args_)
fail_msg_writer() << tr("This is a watch only wallet");
return true;
}
@@ -501,7 +502,7 @@ index b9e30f9d9..f8ed6659c 100644
bool export_raw = false;
std::string unsigned_filename = "unsigned_monero_tx";
-@@ -8034,6 +8193,8 @@ std::string get_tx_key_stream(crypto::secret_key tx_key, std::vector<crypto::sec
+@@ -8034,6 +8194,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_)
{
@@ -510,7 +511,7 @@ index b9e30f9d9..f8ed6659c 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)
-@@ -8074,6 +8235,8 @@ bool simple_wallet::get_tx_key(const std::vector<std::string> &args_)
+@@ -8074,6 +8236,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_)
{
@@ -519,7 +520,7 @@ index b9e30f9d9..f8ed6659c 100644
std::vector<std::string> local_args = args_;
if(local_args.size() != 2 && local_args.size() != 3) {
-@@ -8150,6 +8313,8 @@ bool simple_wallet::set_tx_key(const std::vector<std::string> &args_)
+@@ -8150,6 +8314,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)
{
@@ -528,7 +529,7 @@ index b9e30f9d9..f8ed6659c 100644
if (args.size() != 2 && args.size() != 3)
{
PRINT_USAGE(USAGE_GET_TX_PROOF);
-@@ -8356,6 +8521,7 @@ bool simple_wallet::check_tx_proof(const std::vector<std::string> &args)
+@@ -8356,6 +8522,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)
{
@@ -536,7 +537,7 @@ index b9e30f9d9..f8ed6659c 100644
if (m_wallet->key_on_device())
{
fail_msg_writer() << tr("command not supported by HW wallet");
-@@ -8440,6 +8606,7 @@ bool simple_wallet::check_spend_proof(const std::vector<std::string> &args)
+@@ -8440,6 +8607,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)
{
@@ -544,7 +545,7 @@ index b9e30f9d9..f8ed6659c 100644
if (m_wallet->key_on_device())
{
fail_msg_writer() << tr("command not supported by HW wallet");
-@@ -9126,6 +9293,8 @@ bool simple_wallet::unspent_outputs(const std::vector<std::string> &args_)
+@@ -9126,6 +9294,8 @@ bool simple_wallet::unspent_outputs(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::rescan_blockchain(const std::vector<std::string> &args_)
{
@@ -553,7 +554,7 @@ index b9e30f9d9..f8ed6659c 100644
uint64_t start_height = 0;
ResetType reset_type = ResetSoft;
-@@ -9423,6 +9592,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
+@@ -9423,6 +9593,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
if (command == "new")
{
// create a new account and switch to it
@@ -561,7 +562,7 @@ index b9e30f9d9..f8ed6659c 100644
std::string label = boost::join(local_args, " ");
if (label.empty())
label = tr("(Untitled account)");
-@@ -9453,6 +9623,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
+@@ -9453,6 +9624,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
@@ -569,7 +570,7 @@ index b9e30f9d9..f8ed6659c 100644
uint32_t index_major;
if (!epee::string_tools::get_xtype_from_string(index_major, local_args[0]))
{
-@@ -9474,6 +9645,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
+@@ -9474,6 +9646,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
}
else if (command == "tag" && local_args.size() >= 2)
{
@@ -577,7 +578,7 @@ index b9e30f9d9..f8ed6659c 100644
const std::string tag = local_args[0];
std::set<uint32_t> account_indices;
for (size_t i = 1; i < local_args.size(); ++i)
-@@ -9498,6 +9670,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
+@@ -9498,6 +9671,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
}
else if (command == "untag" && local_args.size() >= 1)
{
@@ -585,7 +586,7 @@ index b9e30f9d9..f8ed6659c 100644
std::set<uint32_t> account_indices;
for (size_t i = 0; i < local_args.size(); ++i)
{
-@@ -9521,6 +9694,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
+@@ -9521,6 +9695,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
}
else if (command == "tag_description" && local_args.size() >= 1)
{
@@ -593,7 +594,7 @@ index b9e30f9d9..f8ed6659c 100644
const std::string tag = local_args[0];
std::string description;
if (local_args.size() > 1)
-@@ -9638,6 +9812,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
+@@ -9638,6 +9813,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
}
else if (local_args[0] == "new")
{
@@ -601,7 +602,7 @@ index b9e30f9d9..f8ed6659c 100644
local_args.erase(local_args.begin());
std::string label;
if (local_args.size() > 0)
-@@ -9650,6 +9825,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
+@@ -9650,6 +9826,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
}
else if (local_args[0] == "mnew")
{
@@ -609,7 +610,7 @@ index b9e30f9d9..f8ed6659c 100644
local_args.erase(local_args.begin());
if (local_args.size() != 1)
{
-@@ -9675,6 +9851,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
+@@ -9675,6 +9852,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
}
else if (local_args[0] == "one-off")
{
@@ -617,7 +618,7 @@ index b9e30f9d9..f8ed6659c 100644
local_args.erase(local_args.begin());
std::string label;
if (local_args.size() != 2)
-@@ -9693,6 +9870,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
+@@ -9693,6 +9871,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
}
else if (local_args.size() >= 2 && local_args[0] == "label")
{
@@ -625,7 +626,7 @@ index b9e30f9d9..f8ed6659c 100644
if (!epee::string_tools::get_xtype_from_string(index, local_args[1]))
{
fail_msg_writer() << tr("failed to parse index: ") << local_args[1];
-@@ -9839,6 +10017,8 @@ bool simple_wallet::print_integrated_address(const std::vector<std::string> &arg
+@@ -9839,6 +10018,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>()*/)
{
@@ -634,7 +635,7 @@ index b9e30f9d9..f8ed6659c 100644
if (args.size() == 0)
{
}
-@@ -9899,6 +10079,8 @@ bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::v
+@@ -9899,6 +10080,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)
{
@@ -643,7 +644,7 @@ index b9e30f9d9..f8ed6659c 100644
if (args.size() == 0)
{
PRINT_USAGE(USAGE_SET_TX_NOTE);
-@@ -9927,6 +10109,8 @@ bool simple_wallet::set_tx_note(const std::vector<std::string> &args)
+@@ -9927,6 +10110,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)
{
@@ -652,7 +653,7 @@ index b9e30f9d9..f8ed6659c 100644
if (args.size() != 1)
{
PRINT_USAGE(USAGE_GET_TX_NOTE);
-@@ -9952,6 +10136,8 @@ bool simple_wallet::get_tx_note(const std::vector<std::string> &args)
+@@ -9952,6 +10137,8 @@ bool simple_wallet::get_tx_note(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::set_description(const std::vector<std::string> &args)
{
@@ -661,7 +662,7 @@ index b9e30f9d9..f8ed6659c 100644
// 0 arguments allowed, for setting the description to empty string
std::string description = "";
-@@ -9968,6 +10154,8 @@ bool simple_wallet::set_description(const std::vector<std::string> &args)
+@@ -9968,6 +10155,8 @@ bool simple_wallet::set_description(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::get_description(const std::vector<std::string> &args)
{
@@ -670,7 +671,7 @@ index b9e30f9d9..f8ed6659c 100644
if (args.size() != 0)
{
PRINT_USAGE(USAGE_GET_DESCRIPTION);
-@@ -10026,6 +10214,8 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args)
+@@ -10026,6 +10215,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();
@@ -679,7 +680,7 @@ index b9e30f9d9..f8ed6659c 100644
else
type = tr("Normal");
message_writer() << tr("Type: ") << type;
-@@ -10037,6 +10227,7 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args)
+@@ -10037,6 +10228,7 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sign(const std::vector<std::string> &args)
{
@@ -687,7 +688,7 @@ index b9e30f9d9..f8ed6659c 100644
if (m_wallet->key_on_device())
{
fail_msg_writer() << tr("command not supported by HW wallet");
-@@ -10144,6 +10335,7 @@ bool simple_wallet::export_key_images(const std::vector<std::string> &args_)
+@@ -10144,6 +10336,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;
}
@@ -695,7 +696,7 @@ index b9e30f9d9..f8ed6659c 100644
auto args = args_;
if (m_wallet->watch_only())
-@@ -10197,6 +10389,7 @@ bool simple_wallet::import_key_images(const std::vector<std::string> &args)
+@@ -10197,6 +10390,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;
}
@@ -703,7 +704,7 @@ index b9e30f9d9..f8ed6659c 100644
if (!m_wallet->is_trusted_daemon())
{
fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon");
-@@ -10305,6 +10498,7 @@ bool simple_wallet::export_outputs(const std::vector<std::string> &args_)
+@@ -10305,6 +10499,7 @@ bool simple_wallet::export_outputs(const std::vector<std::string> &args_)
fail_msg_writer() << tr("command not supported by HW wallet");
return true;
}
@@ -711,7 +712,7 @@ index b9e30f9d9..f8ed6659c 100644
auto args = args_;
bool all = false;
-@@ -10354,6 +10548,7 @@ bool simple_wallet::import_outputs(const std::vector<std::string> &args)
+@@ -10354,6 +10549,7 @@ bool simple_wallet::import_outputs(const std::vector<std::string> &args)
fail_msg_writer() << tr("command not supported by HW wallet");
return true;
}
@@ -720,7 +721,7 @@ index b9e30f9d9..f8ed6659c 100644
{
PRINT_USAGE(USAGE_IMPORT_OUTPUTS);
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
-index 652708f5a..159da2c45 100644
+index 652708f..159da2c 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -147,6 +147,7 @@ namespace cryptonote
@@ -732,7 +733,7 @@ index 652708f5a..159da2c45 100644
bool set_inactivity_lock_timeout(const std::vector<std::string> &args = std::vector<std::string>());
bool set_setup_background_mining(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 d96ea97ea..7d430b655 100644
+index fc4f891..e9f76f4 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -54,6 +54,40 @@ using namespace cryptonote;
@@ -776,7 +777,7 @@ index d96ea97ea..7d430b655 100644
namespace Monero {
namespace {
-@@ -814,6 +848,8 @@ bool WalletImpl::close(bool store)
+@@ -792,6 +826,8 @@ bool WalletImpl::close(bool store)
std::string WalletImpl::seed(const std::string& seed_offset) const
{
@@ -785,7 +786,7 @@ index d96ea97ea..7d430b655 100644
epee::wipeable_string seed;
if (m_wallet)
m_wallet->get_seed(seed, seed_offset);
-@@ -876,6 +912,8 @@ std::string WalletImpl::getSeedLanguage() const
+@@ -805,6 +841,8 @@ std::string WalletImpl::getSeedLanguage() const
void WalletImpl::setSeedLanguage(const std::string &arg)
{
@@ -794,7 +795,7 @@ index d96ea97ea..7d430b655 100644
m_wallet->set_seed_language(arg);
}
-@@ -899,6 +937,8 @@ void WalletImpl::statusWithErrorString(int& status, std::string& errorString) co
+@@ -828,6 +866,8 @@ void WalletImpl::statusWithErrorString(int& status, std::string& errorString) co
bool WalletImpl::setPassword(const std::string &password)
{
@@ -803,7 +804,7 @@ index d96ea97ea..7d430b655 100644
clearStatus();
try {
m_wallet->change_password(m_wallet->get_wallet_file(), m_password, password);
-@@ -1059,6 +1099,8 @@ bool WalletImpl::lightWalletImportWalletRequest(std::string &payment_id, uint64_
+@@ -988,6 +1028,8 @@ bool WalletImpl::lightWalletImportWalletRequest(std::string &payment_id, uint64_
void WalletImpl::setRefreshFromBlockHeight(uint64_t refresh_from_block_height)
{
@@ -812,7 +813,7 @@ index d96ea97ea..7d430b655 100644
m_wallet->set_refresh_from_block_height(refresh_from_block_height);
}
-@@ -1176,6 +1218,8 @@ void WalletImpl::refreshAsync()
+@@ -1105,6 +1147,8 @@ void WalletImpl::refreshAsync()
bool WalletImpl::rescanBlockchain()
{
@@ -821,7 +822,7 @@ index d96ea97ea..7d430b655 100644
clearStatus();
m_refreshShouldRescan = true;
doRefresh();
-@@ -1184,6 +1228,8 @@ bool WalletImpl::rescanBlockchain()
+@@ -1113,6 +1157,8 @@ bool WalletImpl::rescanBlockchain()
void WalletImpl::rescanBlockchainAsync()
{
@@ -830,7 +831,7 @@ index d96ea97ea..7d430b655 100644
m_refreshShouldRescan = true;
refreshAsync();
}
-@@ -1207,7 +1253,7 @@ int WalletImpl::autoRefreshInterval() const
+@@ -1136,7 +1182,7 @@ int WalletImpl::autoRefreshInterval() const
UnsignedTransaction *WalletImpl::loadUnsignedTx(const std::string &unsigned_filename) {
clearStatus();
UnsignedTransactionImpl * transaction = new UnsignedTransactionImpl(*this);
@@ -839,7 +840,7 @@ index d96ea97ea..7d430b655 100644
setStatusError(tr("Failed to load unsigned transactions"));
transaction->m_status = UnsignedTransaction::Status::Status_Error;
transaction->m_errorString = errorString();
-@@ -1227,6 +1273,8 @@ UnsignedTransaction *WalletImpl::loadUnsignedTx(const std::string &unsigned_file
+@@ -1156,6 +1202,8 @@ UnsignedTransaction *WalletImpl::loadUnsignedTx(const std::string &unsigned_file
bool WalletImpl::submitTransaction(const string &fileName) {
clearStatus();
@@ -848,7 +849,7 @@ index d96ea97ea..7d430b655 100644
std::unique_ptr<PendingTransactionImpl> transaction(new PendingTransactionImpl(*this));
bool r = m_wallet->load_tx(fileName, transaction->m_pending_tx);
-@@ -1250,6 +1298,8 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
+@@ -1179,6 +1227,8 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
setStatusError(tr("Wallet is view only"));
return false;
}
@@ -857,7 +858,7 @@ index d96ea97ea..7d430b655 100644
try
{
-@@ -1270,6 +1320,8 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
+@@ -1199,6 +1249,8 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
bool WalletImpl::importKeyImages(const string &filename)
{
@@ -866,7 +867,7 @@ index d96ea97ea..7d430b655 100644
if (!trustedDaemon()) {
setStatusError(tr("Key images can only be imported with a trusted daemon"));
return false;
-@@ -1293,6 +1345,8 @@ bool WalletImpl::importKeyImages(const string &filename)
+@@ -1222,6 +1274,8 @@ bool WalletImpl::importKeyImages(const string &filename)
bool WalletImpl::exportOutputs(const string &filename, bool all)
{
@@ -875,7 +876,7 @@ index d96ea97ea..7d430b655 100644
if (m_wallet->key_on_device())
{
setStatusError(string(tr("Not supported on HW wallets.")) + filename);
-@@ -1323,6 +1377,8 @@ bool WalletImpl::exportOutputs(const string &filename, bool all)
+@@ -1252,6 +1306,8 @@ bool WalletImpl::exportOutputs(const string &filename, bool all)
bool WalletImpl::importOutputs(const string &filename)
{
@@ -884,7 +885,7 @@ index d96ea97ea..7d430b655 100644
if (m_wallet->key_on_device())
{
setStatusError(string(tr("Not supported on HW wallets.")) + filename);
-@@ -1355,6 +1411,8 @@ bool WalletImpl::importOutputs(const string &filename)
+@@ -1284,6 +1340,8 @@ bool WalletImpl::importOutputs(const string &filename)
bool WalletImpl::scanTransactions(const std::vector<std::string> &txids)
{
@@ -893,7 +894,7 @@ index d96ea97ea..7d430b655 100644
if (txids.empty())
{
setStatusError(string(tr("Failed to scan transactions: no transaction ids provided.")));
-@@ -1393,8 +1451,86 @@ bool WalletImpl::scanTransactions(const std::vector<std::string> &txids)
+@@ -1322,8 +1380,86 @@ bool WalletImpl::scanTransactions(const std::vector<std::string> &txids)
return true;
}
@@ -980,7 +981,7 @@ index d96ea97ea..7d430b655 100644
m_wallet->add_subaddress_account(label);
}
size_t WalletImpl::numSubaddressAccounts() const
-@@ -1407,10 +1543,14 @@ size_t WalletImpl::numSubaddresses(uint32_t accountIndex) const
+@@ -1336,10 +1472,14 @@ size_t WalletImpl::numSubaddresses(uint32_t accountIndex) const
}
void WalletImpl::addSubaddress(uint32_t accountIndex, const std::string& label)
{
@@ -995,7 +996,7 @@ index d96ea97ea..7d430b655 100644
try
{
return m_wallet->get_subaddress_label({accountIndex, addressIndex});
-@@ -1424,6 +1564,8 @@ std::string WalletImpl::getSubaddressLabel(uint32_t accountIndex, uint32_t addre
+@@ -1353,6 +1493,8 @@ std::string WalletImpl::getSubaddressLabel(uint32_t accountIndex, uint32_t addre
}
void WalletImpl::setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex, const std::string &label)
{
@@ -1004,7 +1005,7 @@ index d96ea97ea..7d430b655 100644
try
{
return m_wallet->set_subaddress_label({accountIndex, addressIndex}, label);
-@@ -1437,12 +1579,16 @@ void WalletImpl::setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex
+@@ -1366,12 +1508,16 @@ void WalletImpl::setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex
MultisigState WalletImpl::multisig() const {
MultisigState state;
@@ -1021,7 +1022,7 @@ index d96ea97ea..7d430b655 100644
try {
clearStatus();
return m_wallet->get_multisig_first_kex_msg();
-@@ -1455,6 +1601,8 @@ string WalletImpl::getMultisigInfo() const {
+@@ -1384,6 +1530,8 @@ string WalletImpl::getMultisigInfo() const {
}
string WalletImpl::makeMultisig(const vector<string>& info, const uint32_t threshold) {
@@ -1030,7 +1031,7 @@ index d96ea97ea..7d430b655 100644
try {
clearStatus();
-@@ -1595,6 +1743,9 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
+@@ -1524,6 +1672,9 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
do {
@@ -1040,7 +1041,7 @@ index d96ea97ea..7d430b655 100644
std::vector<uint8_t> extra;
std::string extra_nonce;
vector<cryptonote::tx_destination_entry> dsts;
-@@ -1761,6 +1912,9 @@ PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
+@@ -1690,6 +1841,9 @@ PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
do {
@@ -1050,7 +1051,7 @@ index d96ea97ea..7d430b655 100644
try {
transaction->m_pending_tx = m_wallet->create_unmixable_sweep_transactions();
pendingTxPostProcess(transaction);
-@@ -1894,11 +2048,15 @@ uint32_t WalletImpl::defaultMixin() const
+@@ -1823,11 +1977,15 @@ uint32_t WalletImpl::defaultMixin() const
void WalletImpl::setDefaultMixin(uint32_t arg)
{
@@ -1066,7 +1067,7 @@ index d96ea97ea..7d430b655 100644
m_wallet->set_attribute(key, val);
return true;
}
-@@ -1912,6 +2070,8 @@ std::string WalletImpl::getCacheAttribute(const std::string &key) const
+@@ -1841,6 +1999,8 @@ std::string WalletImpl::getCacheAttribute(const std::string &key) const
bool WalletImpl::setUserNote(const std::string &txid, const std::string &note)
{
@@ -1075,7 +1076,7 @@ index d96ea97ea..7d430b655 100644
cryptonote::blobdata txid_data;
if(!epee::string_tools::parse_hexstr_to_binbuff(txid, txid_data) || txid_data.size() != sizeof(crypto::hash))
return false;
-@@ -1923,6 +2083,8 @@ bool WalletImpl::setUserNote(const std::string &txid, const std::string &note)
+@@ -1852,6 +2012,8 @@ bool WalletImpl::setUserNote(const std::string &txid, const std::string &note)
std::string WalletImpl::getUserNote(const std::string &txid) const
{
@@ -1084,7 +1085,7 @@ index d96ea97ea..7d430b655 100644
cryptonote::blobdata txid_data;
if(!epee::string_tools::parse_hexstr_to_binbuff(txid, txid_data) || txid_data.size() != sizeof(crypto::hash))
return "";
-@@ -1933,6 +2095,9 @@ std::string WalletImpl::getUserNote(const std::string &txid) const
+@@ -1862,6 +2024,9 @@ std::string WalletImpl::getUserNote(const std::string &txid) const
std::string WalletImpl::getTxKey(const std::string &txid_str) const
{
@@ -1094,7 +1095,7 @@ index d96ea97ea..7d430b655 100644
crypto::hash txid;
if(!epee::string_tools::hex_to_pod(txid_str, txid))
{
-@@ -2017,6 +2182,9 @@ bool WalletImpl::checkTxKey(const std::string &txid_str, std::string tx_key_str,
+@@ -1946,6 +2111,9 @@ bool WalletImpl::checkTxKey(const std::string &txid_str, std::string tx_key_str,
std::string WalletImpl::getTxProof(const std::string &txid_str, const std::string &address_str, const std::string &message) const
{
@@ -1104,7 +1105,7 @@ index d96ea97ea..7d430b655 100644
crypto::hash txid;
if (!epee::string_tools::hex_to_pod(txid_str, txid))
{
-@@ -2073,6 +2241,9 @@ bool WalletImpl::checkTxProof(const std::string &txid_str, const std::string &ad
+@@ -2002,6 +2170,9 @@ bool WalletImpl::checkTxProof(const std::string &txid_str, const std::string &ad
}
std::string WalletImpl::getSpendProof(const std::string &txid_str, const std::string &message) const {
@@ -1114,7 +1115,7 @@ index d96ea97ea..7d430b655 100644
crypto::hash txid;
if(!epee::string_tools::hex_to_pod(txid_str, txid))
{
-@@ -2115,6 +2286,9 @@ bool WalletImpl::checkSpendProof(const std::string &txid_str, const std::string
+@@ -2044,6 +2215,9 @@ bool WalletImpl::checkSpendProof(const std::string &txid_str, const std::string
}
std::string WalletImpl::getReserveProof(bool all, uint32_t account_index, uint64_t amount, const std::string &message) const {
@@ -1124,7 +1125,7 @@ index d96ea97ea..7d430b655 100644
try
{
clearStatus();
-@@ -2161,6 +2335,9 @@ bool WalletImpl::checkReserveProof(const std::string &address, const std::string
+@@ -2090,6 +2264,9 @@ bool WalletImpl::checkReserveProof(const std::string &address, const std::string
std::string WalletImpl::signMessage(const std::string &message, const std::string &address)
{
@@ -1134,7 +1135,7 @@ index d96ea97ea..7d430b655 100644
if (address.empty()) {
return m_wallet->sign(message, tools::wallet2::sign_with_spend_key);
}
-@@ -2288,6 +2465,16 @@ bool WalletImpl::isDeterministic() const
+@@ -2217,6 +2394,16 @@ bool WalletImpl::isDeterministic() const
return m_wallet->is_deterministic();
}
@@ -1151,7 +1152,7 @@ index d96ea97ea..7d430b655 100644
void WalletImpl::clearStatus() const
{
boost::lock_guard<boost::mutex> l(m_statusMutex);
-@@ -2356,9 +2543,7 @@ void WalletImpl::doRefresh()
+@@ -2285,9 +2472,7 @@ void WalletImpl::doRefresh()
if(rescan)
m_wallet->rescan_blockchain(false);
m_wallet->refresh(trustedDaemon());
@@ -1162,7 +1163,7 @@ index d96ea97ea..7d430b655 100644
// 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
-@@ -2462,6 +2647,24 @@ bool WalletImpl::doInit(const string &daemon_address, const std::string &proxy_a
+@@ -2391,6 +2576,24 @@ bool WalletImpl::doInit(const string &daemon_address, const std::string &proxy_a
return true;
}
@@ -1187,7 +1188,7 @@ index d96ea97ea..7d430b655 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);
-@@ -2480,6 +2683,8 @@ std::string WalletImpl::getDefaultDataDir() const
+@@ -2409,6 +2612,8 @@ std::string WalletImpl::getDefaultDataDir() const
bool WalletImpl::rescanSpent()
{
clearStatus();
@@ -1197,10 +1198,10 @@ index d96ea97ea..7d430b655 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 787215ab3..9acd2871f 100644
+index ec2d7e9..1f199a7 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
-@@ -181,6 +181,13 @@ public:
+@@ -171,6 +171,13 @@ public:
bool importOutputs(const std::string &filename) override;
bool scanTransactions(const std::vector<std::string> &txids) override;
@@ -1214,7 +1215,7 @@ index 787215ab3..9acd2871f 100644
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;
-@@ -249,6 +256,7 @@ private:
+@@ -239,6 +246,7 @@ private:
bool isNewWallet() const;
void pendingTxPostProcess(PendingTransactionImpl * pending);
bool doInit(const std::string &daemon_address, const std::string &proxy_address, uint64_t upper_transaction_size_limit = 0, bool ssl = false);
@@ -1222,7 +1223,7 @@ index 787215ab3..9acd2871f 100644
private:
friend class PendingTransactionImpl;
-@@ -263,6 +271,10 @@ private:
+@@ -253,6 +261,10 @@ private:
mutable boost::mutex m_statusMutex;
mutable int m_status;
mutable std::string m_errorString;
@@ -1234,7 +1235,7 @@ index 787215ab3..9acd2871f 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 9ea753083..4268b656e 100644
+index 71991df..e349df1 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -445,6 +445,12 @@ struct Wallet
@@ -1250,7 +1251,7 @@ index 9ea753083..4268b656e 100644
virtual ~Wallet() = 0;
virtual std::string seed(const std::string& seed_offset = "") const = 0;
virtual std::string getSeedLanguage() const = 0;
-@@ -940,6 +946,42 @@ struct Wallet
+@@ -936,6 +942,42 @@ struct Wallet
*/
virtual bool scanTransactions(const std::vector<std::string> &txids) = 0;
@@ -1294,10 +1295,10 @@ 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 9e95f44d6..f2381740a 100644
+index ad8c361..8146014 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
-@@ -158,6 +158,8 @@ static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1";
+@@ -157,6 +157,8 @@ static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1";
static const std::string ASCII_OUTPUT_MAGIC = "MoneroAsciiDataV1";
@@ -1306,7 +1307,7 @@ index 9e95f44d6..f2381740a 100644
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)
+@@ -1009,14 +1011,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
*/
@@ -1323,7 +1324,7 @@ index 9e95f44d6..f2381740a 100644
cn_fast_hash(cache_key_data.data(), HASH_SIZE+1, (crypto::hash&) cache_key);
return cache_key;
-@@ -1105,7 +1107,7 @@ wallet_keys_unlocker::wallet_keys_unlocker(wallet2 &w, const boost::optional<too
+@@ -1104,7 +1106,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;
@@ -1332,7 +1333,7 @@ index 9e95f44d6..f2381740a 100644
{
locked = false;
return;
-@@ -1222,6 +1224,11 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
+@@ -1221,6 +1223,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),
@@ -1344,7 +1345,7 @@ index 9e95f44d6..f2381740a 100644
m_show_wallet_name_when_locked(false),
m_inactivity_lock_timeout(DEFAULT_INACTIVITY_LOCK_TIMEOUT),
m_setup_background_mining(BackgroundMiningMaybe),
-@@ -1877,6 +1884,9 @@ bool has_nonrequested_tx_at_height_or_above_requested(uint64_t height, const std
+@@ -1860,6 +1867,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)
{
@@ -1354,7 +1355,7 @@ index 9e95f44d6..f2381740a 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 +2194,11 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons
+@@ -2167,11 +2177,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
@@ -1368,7 +1369,7 @@ index 9e95f44d6..f2381740a 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 +2210,7 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons
+@@ -2183,7 +2193,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");
@@ -1377,7 +1378,7 @@ index 9e95f44d6..f2381740a 100644
{
tx_scan_info.in_ephemeral.pub = output_public_key;
tx_scan_info.in_ephemeral.sec = crypto::null_skey;
-@@ -2457,6 +2467,22 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+@@ -2440,6 +2450,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()));
@@ -1400,7 +1401,7 @@ index 9e95f44d6..f2381740a 100644
}
for(size_t o: outs)
-@@ -2482,7 +2508,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+@@ -2465,7 +2491,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;
@@ -1409,7 +1410,7 @@ index 9e95f44d6..f2381740a 100644
if (!td.m_key_image_known)
{
// we might have cold signed, and have a mapping to key images
-@@ -2672,10 +2698,25 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+@@ -2655,10 +2681,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);
@@ -1436,7 +1437,7 @@ index 9e95f44d6..f2381740a 100644
{
PERF_TIMER(track_uses);
const uint64_t amount = in_to_key.amount;
-@@ -2689,7 +2730,27 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+@@ -2672,7 +2713,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");
@@ -1465,7 +1466,7 @@ index 9e95f44d6..f2381740a 100644
}
}
}
-@@ -2699,7 +2760,24 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+@@ -2682,7 +2743,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)
@@ -1491,7 +1492,7 @@ index 9e95f44d6..f2381740a 100644
}
}
}
-@@ -3072,8 +3150,8 @@ void wallet2::pull_blocks(bool first, bool try_incremental, uint64_t start_heigh
+@@ -3055,8 +3133,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;
@@ -1502,7 +1503,7 @@ index 9e95f44d6..f2381740a 100644
req.pool_info_since = m_pool_info_query_time;
{
-@@ -3100,7 +3178,7 @@ void wallet2::pull_blocks(bool first, bool try_incremental, uint64_t start_heigh
+@@ -3083,7 +3161,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));
@@ -1511,7 +1512,7 @@ index 9e95f44d6..f2381740a 100644
{
if (res.pool_info_extent != COMMAND_RPC_GET_BLOCKS_FAST::NONE)
{
-@@ -3612,6 +3690,9 @@ void wallet2::process_unconfirmed_transfer(bool incremental, const crypto::hash
+@@ -3595,6 +3673,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)
{
@@ -1521,7 +1522,7 @@ index 9e95f44d6..f2381740a 100644
bool updated = false;
if (m_pool_info_query_time != 0 && try_incremental)
{
-@@ -4183,6 +4264,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
+@@ -4166,6 +4247,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
}
m_first_refresh_done = true;
@@ -1530,7 +1531,7 @@ index 9e95f44d6..f2381740a 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)));
}
-@@ -4268,6 +4351,14 @@ wallet2::detached_blockchain_data wallet2::detach_blockchain(uint64_t height, st
+@@ -4251,6 +4334,14 @@ wallet2::detached_blockchain_data wallet2::detach_blockchain(uint64_t height, st
td.m_uses.pop_back();
}
@@ -1545,7 +1546,7 @@ index 9e95f44d6..f2381740a 100644
if (output_tracker_cache)
output_tracker_cache->clear();
-@@ -4342,8 +4433,12 @@ void wallet2::handle_reorg(uint64_t height, std::map<std::pair<uint64_t, uint64_
+@@ -4325,8 +4416,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");
@@ -1558,7 +1559,7 @@ index 9e95f44d6..f2381740a 100644
if (m_callback)
m_callback->on_reorg(height, dbd.detached_blockchain.size(), dbd.detached_tx_hashes.size());
}
-@@ -4353,6 +4448,7 @@ bool wallet2::deinit()
+@@ -4336,6 +4431,7 @@ bool wallet2::deinit()
if(m_is_initialized) {
m_is_initialized = false;
unlock_keys_file();
@@ -1566,7 +1567,7 @@ index 9e95f44d6..f2381740a 100644
m_account.deinit();
}
return true;
-@@ -4379,6 +4475,7 @@ bool wallet2::clear()
+@@ -4362,6 +4458,7 @@ bool wallet2::clear()
m_device_last_key_image_sync = 0;
m_pool_info_query_time = 0;
m_skip_to_height = 0;
@@ -1574,7 +1575,7 @@ index 9e95f44d6..f2381740a 100644
return true;
}
//----------------------------------------------------------------------------------------------------
-@@ -4397,13 +4494,30 @@ void wallet2::clear_soft(bool keep_key_images)
+@@ -4380,13 +4477,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;
@@ -1606,7 +1607,7 @@ index 9e95f44d6..f2381740a 100644
/*!
* \brief Stores wallet information to wallet file.
* \param keys_file_name Name of wallet file
-@@ -4415,16 +4529,35 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
+@@ -4398,16 +4512,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");
@@ -1646,7 +1647,7 @@ index 9e95f44d6..f2381740a 100644
if (e) {
boost::filesystem::remove(tmp_file_name);
-@@ -4436,26 +4569,27 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
+@@ -4419,26 +4552,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)
@@ -1682,7 +1683,7 @@ index 9e95f44d6..f2381740a 100644
account.forget_spend_key();
account.encrypt_keys(key);
-@@ -4590,6 +4724,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
+@@ -4573,6 +4707,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());
@@ -1692,19 +1693,20 @@ index 9e95f44d6..f2381740a 100644
value2.SetInt(m_show_wallet_name_when_locked ? 1 : 0);
json.AddMember("show_wallet_name_when_locked", value2, json.GetAllocator());
-@@ -4649,6 +4786,11 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
+@@ -4630,6 +4767,12 @@ 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());
- 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());
+ }
-
++
// Serialize the JSON object
rapidjson::StringBuffer buffer;
-@@ -4676,13 +4818,81 @@ void wallet2::setup_keys(const epee::wipeable_string &password)
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+@@ -4656,13 +4799,81 @@ void wallet2::setup_keys(const epee::wipeable_string &password)
m_account.decrypt_viewkey(key);
}
@@ -1787,7 +1789,7 @@ index 9e95f44d6..f2381740a 100644
if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only)
decrypt_keys(original_password);
setup_keys(new_password);
-@@ -4741,8 +4951,24 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+@@ -4721,8 +4932,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]);
@@ -1813,7 +1815,7 @@ index 9e95f44d6..f2381740a 100644
// The contents should be JSON if the wallet follows the new format.
if (json.Parse(account_data.c_str()).HasParseError())
{
-@@ -4780,6 +5006,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+@@ -4760,6 +4987,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;
@@ -1821,18 +1823,18 @@ index 9e95f44d6..f2381740a 100644
m_show_wallet_name_when_locked = false;
m_inactivity_lock_timeout = DEFAULT_INACTIVITY_LOCK_TIMEOUT;
m_setup_background_mining = BackgroundMiningMaybe;
-@@ -4798,6 +5025,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+@@ -4777,6 +5005,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_polyseed = false;
+ m_custom_background_key = boost::none;
}
else if(json.IsObject())
{
-@@ -5036,6 +5264,39 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+@@ -5013,6 +5242,39 @@ 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;
- 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;
@@ -1869,7 +1871,7 @@ index 9e95f44d6..f2381740a 100644
}
else
{
-@@ -5099,12 +5360,17 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+@@ -5076,12 +5338,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);
@@ -1889,7 +1891,7 @@ index 9e95f44d6..f2381740a 100644
return true;
}
-@@ -5119,11 +5385,12 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+@@ -5096,11 +5363,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
*
*/
@@ -1904,7 +1906,7 @@ index 9e95f44d6..f2381740a 100644
lock_keys_file();
return r;
}
-@@ -5141,7 +5408,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password)
+@@ -5118,7 +5386,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
*
*/
@@ -1913,7 +1915,7 @@ index 9e95f44d6..f2381740a 100644
{
rapidjson::Document json;
wallet2::keys_file_data keys_file_data;
-@@ -5158,9 +5425,22 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
+@@ -5135,9 +5403,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]);
@@ -1937,7 +1939,7 @@ index 9e95f44d6..f2381740a 100644
// The contents should be JSON if the wallet follows the new format.
if (json.Parse(account_data.c_str()).HasParseError())
{
-@@ -5185,6 +5465,7 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
+@@ -5162,6 +5443,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);
@@ -1945,7 +1947,7 @@ index 9e95f44d6..f2381740a 100644
return r;
}
-@@ -5196,9 +5477,7 @@ void wallet2::encrypt_keys(const crypto::chacha_key &key)
+@@ -5173,9 +5455,7 @@ void wallet2::encrypt_keys(const crypto::chacha_key &key)
void wallet2::decrypt_keys(const crypto::chacha_key &key)
{
@@ -1956,7 +1958,7 @@ index 9e95f44d6..f2381740a 100644
m_account.encrypt_viewkey(key);
m_account.decrypt_keys(key);
-@@ -5916,11 +6195,30 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin
+@@ -5851,11 +6131,30 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin
{
if (wallet_name.empty())
return;
@@ -1987,7 +1989,7 @@ index 9e95f44d6..f2381740a 100644
}
/*!
* \brief Writes to a file named based on the normal wallet (doesn't generate key, assumes it's already there)
-@@ -5954,6 +6252,16 @@ bool wallet2::wallet_valid_path_format(const std::string& file_path)
+@@ -5889,6 +6188,16 @@ bool wallet2::wallet_valid_path_format(const std::string& file_path)
return !file_path.empty();
}
//----------------------------------------------------------------------------------------------------
@@ -2004,7 +2006,7 @@ index 9e95f44d6..f2381740a 100644
bool wallet2::parse_long_payment_id(const std::string& payment_id_str, crypto::hash& payment_id)
{
cryptonote::blobdata payment_id_data;
-@@ -6189,10 +6497,81 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
+@@ -6124,10 +6433,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");
}
@@ -2087,7 +2089,7 @@ index 9e95f44d6..f2381740a 100644
bool cache_missing = use_fs ? (!boost::filesystem::exists(m_wallet_file, e) || e) : cache_buf.empty();
if (cache_missing)
{
-@@ -6206,7 +6585,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
+@@ -6141,7 +6521,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
bool r = true;
if (use_fs)
{
@@ -2096,7 +2098,7 @@ index 9e95f44d6..f2381740a 100644
THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, m_wallet_file);
}
-@@ -6219,7 +6598,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
+@@ -6154,7 +6534,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());
@@ -2105,7 +2107,7 @@ index 9e95f44d6..f2381740a 100644
try {
bool loaded = false;
-@@ -6309,60 +6688,76 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
+@@ -6244,60 +6624,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);
}
@@ -2224,7 +2226,7 @@ index 9e95f44d6..f2381740a 100644
}
}
//----------------------------------------------------------------------------------------------------
-@@ -6444,6 +6839,8 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
+@@ -6379,6 +6775,8 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
same_file = canonical_old_path == canonical_new_path;
}
@@ -2233,7 +2235,7 @@ index 9e95f44d6..f2381740a 100644
if (!same_file)
{
-@@ -6460,6 +6857,21 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
+@@ -6395,6 +6793,21 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
}
}
}
@@ -2255,7 +2257,7 @@ index 9e95f44d6..f2381740a 100644
// get wallet cache data
boost::optional<wallet2::cache_file_data> cache_file_data = get_cache_file_data();
-@@ -6553,6 +6965,22 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
+@@ -6488,6 +6901,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);
}
@@ -2278,7 +2280,7 @@ index 9e95f44d6..f2381740a 100644
}
//----------------------------------------------------------------------------------------------------
boost::optional<wallet2::cache_file_data> wallet2::get_cache_file_data()
-@@ -6570,7 +6998,7 @@ boost::optional<wallet2::cache_file_data> wallet2::get_cache_file_data()
+@@ -6505,7 +6934,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>();
@@ -2287,7 +2289,7 @@ index 9e95f44d6..f2381740a 100644
cache_file_data.get().cache_data = cipher;
return cache_file_data;
}
-@@ -8646,6 +9074,34 @@ bool wallet2::is_keys_file_locked() const
+@@ -8581,6 +9010,34 @@ bool wallet2::is_keys_file_locked() const
return m_keys_file_locker->locked();
}
@@ -2322,7 +2324,7 @@ index 9e95f44d6..f2381740a 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
-@@ -13978,6 +14434,413 @@ bool wallet2::import_key_images(signed_tx_set & signed_tx, size_t offset, bool o
+@@ -13913,6 +14370,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);
}
@@ -2737,10 +2739,10 @@ index 9e95f44d6..f2381740a 100644
{
payment_container payments;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
-index 91ec72e0f..56cc118f4 100644
+index 24366f6..b1dc4f7 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
-@@ -257,6 +257,20 @@ private:
+@@ -256,6 +256,20 @@ private:
BackgroundMiningNo = 2,
};
@@ -2761,7 +2763,7 @@ index 91ec72e0f..56cc118f4 100644
enum ExportFormat {
Binary = 0,
Ascii,
-@@ -283,7 +297,12 @@ private:
+@@ -282,7 +296,12 @@ private:
//! Just parses variables.
static std::unique_ptr<wallet2> make_dummy(const boost::program_options::variables_map& vm, bool unattended, const std::function<boost::optional<password_container>(const char *, bool)> &password_prompter);
@@ -2775,7 +2777,7 @@ index 91ec72e0f..56cc118f4 100644
static bool query_device(hw::device::device_type& device_type, const std::string& keys_file_name, const epee::wipeable_string& password, uint64_t kdf_rounds = 1);
wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, uint64_t kdf_rounds = 1, bool unattended = false, std::unique_ptr<epee::net_utils::http::http_client_factory> http_client_factory = std::unique_ptr<epee::net_utils::http::http_client_factory>(new net::http::client_factory()));
-@@ -793,6 +812,54 @@ private:
+@@ -792,6 +811,54 @@ private:
END_SERIALIZE()
};
@@ -2830,7 +2832,7 @@ index 91ec72e0f..56cc118f4 100644
typedef std::tuple<uint64_t, crypto::public_key, rct::key> get_outs_entry;
struct parsed_block
-@@ -989,7 +1056,8 @@ private:
+@@ -974,7 +1041,8 @@ private:
/*!
* \brief verifies given password is correct for default wallet keys file
*/
@@ -2840,7 +2842,7 @@ index 91ec72e0f..56cc118f4 100644
cryptonote::account_base& get_account(){return m_account;}
const cryptonote::account_base& get_account()const{return m_account;}
-@@ -1093,6 +1161,7 @@ private:
+@@ -1069,6 +1137,7 @@ private:
cryptonote::network_type nettype() const { return m_nettype; }
bool watch_only() const { return m_watch_only; }
bool multisig(bool *ready = NULL, uint32_t *threshold = NULL, uint32_t *total = NULL) const;
@@ -2848,7 +2850,7 @@ index 91ec72e0f..56cc118f4 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,11 +1369,17 @@ private:
+@@ -1276,11 +1345,17 @@ private:
return;
}
a & m_has_ever_refreshed_from_node;
@@ -2867,7 +2869,7 @@ index 91ec72e0f..56cc118f4 100644
FIELD(m_blockchain)
FIELD(m_transfers)
FIELD(m_account_public_address)
-@@ -1336,6 +1411,12 @@ private:
+@@ -1312,6 +1387,12 @@ private:
return true;
}
FIELD(m_has_ever_refreshed_from_node)
@@ -2880,7 +2882,7 @@ index 91ec72e0f..56cc118f4 100644
END_SERIALIZE()
/*!
-@@ -1351,6 +1432,8 @@ private:
+@@ -1327,6 +1408,8 @@ private:
* \return Whether path is valid format
*/
static bool wallet_valid_path_format(const std::string& file_path);
@@ -2889,7 +2891,7 @@ index 91ec72e0f..56cc118f4 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 +1482,9 @@ private:
+@@ -1375,6 +1458,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; }
@@ -2899,7 +2901,7 @@ index 91ec72e0f..56cc118f4 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; }
-@@ -1714,6 +1800,9 @@ private:
+@@ -1689,6 +1775,9 @@ private:
uint64_t get_bytes_sent() const;
uint64_t get_bytes_received() const;
@@ -2909,7 +2911,7 @@ index 91ec72e0f..56cc118f4 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 +1838,9 @@ private:
+@@ -1724,6 +1813,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);
@@ -2919,7 +2921,7 @@ index 91ec72e0f..56cc118f4 100644
/*!
* \brief Load wallet keys information from wallet file.
* \param keys_file_name Name of wallet file
-@@ -1762,6 +1854,7 @@ private:
+@@ -1737,6 +1829,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);
@@ -2927,7 +2929,7 @@ index 91ec72e0f..56cc118f4 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 +1863,15 @@ private:
+@@ -1745,6 +1838,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);
@@ -2943,7 +2945,7 @@ index 91ec72e0f..56cc118f4 100644
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 +1923,23 @@ private:
+@@ -1796,10 +1898,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);
@@ -2967,7 +2969,7 @@ index 91ec72e0f..56cc118f4 100644
void register_devices();
hw::device& lookup_device(const std::string & device_descriptor);
-@@ -1940,6 +2055,8 @@ private:
+@@ -1914,6 +2029,8 @@ private:
uint64_t m_ignore_outputs_above;
uint64_t m_ignore_outputs_below;
bool m_track_uses;
@@ -2976,7 +2978,7 @@ index 91ec72e0f..56cc118f4 100644
bool m_show_wallet_name_when_locked;
uint32_t m_inactivity_lock_timeout;
BackgroundMiningSetupType m_setup_background_mining;
-@@ -1985,6 +2102,7 @@ private:
+@@ -1959,6 +2076,7 @@ private:
uint64_t m_last_block_reward;
std::unique_ptr<tools::file_locker> m_keys_file_locker;
@@ -2984,7 +2986,7 @@ index 91ec72e0f..56cc118f4 100644
mms::message_store m_message_store;
bool m_original_keys_available;
-@@ -1992,6 +2110,7 @@ private:
+@@ -1966,6 +2084,7 @@ private:
crypto::secret_key m_original_view_secret_key;
crypto::chacha_key m_cache_key;
@@ -2992,7 +2994,7 @@ index 91ec72e0f..56cc118f4 100644
std::shared_ptr<wallet_keys_unlocker> m_encrypt_keys_after_refresh;
bool m_unattended;
-@@ -2007,9 +2126,13 @@ private:
+@@ -1981,9 +2100,13 @@ private:
static boost::mutex default_daemon_address_lock;
static std::string default_daemon_address;
@@ -3007,7 +3009,7 @@ index 91ec72e0f..56cc118f4 100644
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)
+@@ -1999,6 +2122,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)
@@ -3016,7 +3018,7 @@ index 91ec72e0f..56cc118f4 100644
namespace boost
{
-@@ -2523,6 +2648,29 @@ namespace boost
+@@ -2497,6 +2622,29 @@ namespace boost
return;
a & x.multisig_sigs;
}
@@ -3047,7 +3049,7 @@ index 91ec72e0f..56cc118f4 100644
}
diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h
-index c077313d4..c54cd3499 100644
+index c077313..c54cd34 100644
--- a/src/wallet/wallet_errors.h
+++ b/src/wallet/wallet_errors.h
@@ -63,6 +63,7 @@ namespace tools
@@ -3118,7 +3120,7 @@ index c077313d4..c54cd3499 100644
#if !defined(_MSC_VER)
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
-index b1419949f..d24b4c563 100644
+index b141994..d24b4c5 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -73,6 +73,54 @@ using namespace epee;
@@ -3564,7 +3566,7 @@ index b1419949f..d24b4c563 100644
try
{
diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h
-index 3308d1751..c2329aafe 100644
+index 3308d17..c2329aa 100644
--- a/src/wallet/wallet_rpc_server.h
+++ b/src/wallet/wallet_rpc_server.h
@@ -160,6 +160,9 @@ namespace tools
@@ -3588,7 +3590,7 @@ index 3308d1751..c2329aafe 100644
//json rpc v2
bool on_query_key(const wallet_rpc::COMMAND_RPC_QUERY_KEY::request& req, wallet_rpc::COMMAND_RPC_QUERY_KEY::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);
diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h
-index b6098d95c..a44b56ed6 100644
+index b6098d9..a44b56e 100644
--- a/src/wallet/wallet_rpc_server_commands_defs.h
+++ b/src/wallet/wallet_rpc_server_commands_defs.h
@@ -2696,5 +2696,69 @@ namespace wallet_rpc
@@ -3662,7 +3664,7 @@ index b6098d95c..a44b56ed6 100644
}
}
diff --git a/src/wallet/wallet_rpc_server_error_codes.h b/src/wallet/wallet_rpc_server_error_codes.h
-index 541d29f86..6e88f6967 100644
+index 541d29f..4756c19 100644
--- a/src/wallet/wallet_rpc_server_error_codes.h
+++ b/src/wallet/wallet_rpc_server_error_codes.h
@@ -81,3 +81,5 @@
@@ -3671,9 +3673,8 @@ index 541d29f86..6e88f6967 100644
#define WALLET_RPC_ERROR_CODE_NONZERO_UNLOCK_TIME -50
+#define WALLET_RPC_ERROR_CODE_IS_BACKGROUND_WALLET -51
+#define WALLET_RPC_ERROR_CODE_IS_BACKGROUND_SYNCING -52
-\ No newline at end of file
diff --git a/tests/functional_tests/transfer.py b/tests/functional_tests/transfer.py
-index 4063911f4..60eb09a10 100755
+index 4063911..60eb09a 100755
--- a/tests/functional_tests/transfer.py
+++ b/tests/functional_tests/transfer.py
@@ -30,6 +30,7 @@
@@ -4111,7 +4112,7 @@ index 4063911f4..60eb09a10 100755
if __name__ == '__main__':
TransferTest().run_test()
diff --git a/tests/functional_tests/util_resources.py b/tests/functional_tests/util_resources.py
-index e030312da..3ca6fdb86 100755
+index e030312..3ca6fdb 100755
--- a/tests/functional_tests/util_resources.py
+++ b/tests/functional_tests/util_resources.py
@@ -37,6 +37,8 @@
@@ -4151,7 +4152,7 @@ index e030312da..3ca6fdb86 100755
+ assert WALLET_DIRECTORY != ''
+ return os.path.isfile(WALLET_DIRECTORY + '/' + name)
diff --git a/tests/functional_tests/wallet.py b/tests/functional_tests/wallet.py
-index 1ad05c98f..8182cecb2 100755
+index 1ad05c9..8182cec 100755
--- a/tests/functional_tests/wallet.py
+++ b/tests/functional_tests/wallet.py
@@ -34,8 +34,7 @@
@@ -4242,7 +4243,7 @@ index 1ad05c98f..8182cecb2 100755
if __name__ == '__main__':
diff --git a/tests/unit_tests/wipeable_string.cpp b/tests/unit_tests/wipeable_string.cpp
-index ef6964f9e..25121a02e 100644
+index ef6964f..25121a0 100644
--- a/tests/unit_tests/wipeable_string.cpp
+++ b/tests/unit_tests/wipeable_string.cpp
@@ -211,3 +211,15 @@ TEST(wipeable_string, to_hex)
@@ -4262,7 +4263,7 @@ 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..bff33a561 100644
+index 1e10e1f..bff33a5 100644
--- a/utils/python-rpc/framework/wallet.py
+++ b/utils/python-rpc/framework/wallet.py
@@ -1138,3 +1138,45 @@ class Wallet(object):
@@ -4312,5 +4313,5 @@ index 1e10e1f86..bff33a561 100644
+ }
+ return self.rpc.send_json_rpc_request(stop_background_sync)
--
-2.39.2
+2.39.5 (Apple Git-154)
diff --git a/patches/monero/0008-fix-missing-___clear_cache-when-targetting-iOS.patch b/patches/monero/0002-fix-missing-___clear_cache-when-targetting-iOS.patch
index 5b46d7c..2b13c05 100644
--- a/patches/monero/0008-fix-missing-___clear_cache-when-targetting-iOS.patch
+++ b/patches/monero/0002-fix-missing-___clear_cache-when-targetting-iOS.patch
@@ -1,33 +1,34 @@
-From c7f8510fb4bfb54707053603f5cbcaa8c0bf72d2 Mon Sep 17 00:00:00 2001
+From c7b6e26d36d2428e5747e2b8287ae3719fa443e3 Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Tue, 2 Apr 2024 16:51:56 +0200
-Subject: [PATCH 08/16] fix missing ___clear_cache when targetting iOS
+Subject: [PATCH 02/14] fix missing ___clear_cache when targetting iOS
---
- .gitmodules | 2 +-
+ .gitmodules | 3 ++-
external/randomx | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
+ 2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/.gitmodules b/.gitmodules
-index 73a23fb35..7ea87a009 100644
+index 721cce3..ffb73fe 100644
--- a/.gitmodules
+++ b/.gitmodules
-@@ -9,7 +9,7 @@
+@@ -9,7 +9,8 @@
url = https://github.com/trezor/trezor-common.git
[submodule "external/randomx"]
path = external/randomx
- url = https://github.com/tevador/RandomX
+ url = https://github.com/MrCyjaneK/RandomX
- [submodule "external/utf8proc"]
- path = external/utf8proc
- url = https://github.com/JuliaStrings/utf8proc.git
++ branch = cyjan-fix-ios
+ [submodule "external/supercop"]
+ path = external/supercop
+ url = https://github.com/monero-project/supercop
diff --git a/external/randomx b/external/randomx
-index 102f8acf9..ce72c9bb9 160000
+index 102f8ac..ce72c9b 160000
--- a/external/randomx
+++ b/external/randomx
@@ -1 +1 @@
-Subproject commit 102f8acf90a7649ada410de5499a7ec62e49e1da
+Subproject commit ce72c9bb9cb799e0d9171094b9abb009e04c5bfc
--
-2.39.2
+2.39.5 (Apple Git-154)
diff --git a/patches/monero/0003-airgap.patch b/patches/monero/0003-airgap.patch
deleted file mode 100644
index eebe097..0000000
--- a/patches/monero/0003-airgap.patch
+++ /dev/null
@@ -1,195 +0,0 @@
-From 5385d085c547b675adfccb64314d1c6f7bf2d508 Mon Sep 17 00:00:00 2001
-From: tobtoht <tob@featherwallet.org>
-Date: Tue, 12 Mar 2024 10:09:50 +0100
-Subject: [PATCH 03/16] airgap
-
----
- src/wallet/api/wallet.cpp | 23 ++++++++++++++++++
- src/wallet/api/wallet.h | 2 ++
- src/wallet/api/wallet2_api.h | 3 +++
- src/wallet/wallet2.cpp | 45 +++++++++++++++++++++++++++++++-----
- src/wallet/wallet2.h | 1 +
- 5 files changed, 68 insertions(+), 6 deletions(-)
-
-diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index 7d430b655..837b98e6b 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
- return m_wallet->unlocked_balance(accountIndex, false);
- }
-
-+uint64_t WalletImpl::viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images) const
-+{
-+ clearStatus();
-+
-+ std::vector<crypto::key_image> kis;
-+ for (const auto &key_image : key_images) {
-+ crypto::key_image ki;
-+ if (!epee::string_tools::hex_to_pod(key_image, ki))
-+ {
-+ setStatusError(tr("failed to parse key image"));
-+ return 0;
-+ }
-+ kis.push_back(ki);
-+ }
-+
-+ return m_wallet->view_only_balance(accountIndex, kis);
-+}
-+
- uint64_t WalletImpl::blockChainHeight() const
- {
- if(m_wallet->light_wallet()) {
-@@ -1291,6 +1309,11 @@ bool WalletImpl::submitTransaction(const string &fileName) {
- return true;
- }
-
-+bool WalletImpl::hasUnknownKeyImages() const
-+{
-+ return m_wallet->has_unknown_key_images();
-+}
-+
- bool WalletImpl::exportKeyImages(const string &filename, bool all)
- {
- if (m_wallet->watch_only())
-diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
-index 9acd2871f..05d065c5c 100644
---- a/src/wallet/api/wallet.h
-+++ b/src/wallet/api/wallet.h
-@@ -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;
-+ uint64_t viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images) const override;
- 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;
- virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override;
-+ bool hasUnknownKeyImages() const 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
---- a/src/wallet/api/wallet2_api.h
-+++ b/src/wallet/api/wallet2_api.h
-@@ -626,6 +626,7 @@ struct Wallet
- result += unlockedBalance(i);
- return result;
- }
-+ virtual uint64_t viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images = {}) const = 0;
-
- /**
- * @brief watchOnly - checks if wallet is watch only
-@@ -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;
-
-+ virtual bool hasUnknownKeyImages() const = 0;
-+
- /*!
- * \brief exportKeyImages - exports key images to file
- * \param filename
-diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
-index f2381740a..41cf1fd41 100644
---- a/src/wallet/wallet2.cpp
-+++ b/src/wallet/wallet2.cpp
-@@ -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);
-@@ -7038,6 +7048,25 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t *
- return amount;
- }
- //----------------------------------------------------------------------------------------------------
-+uint64_t wallet2::view_only_balance(uint32_t index_major, const std::vector<crypto::key_image>& selected_inputs)
-+{
-+ uint64_t amount = 0;
-+ for (const auto &td : m_transfers) {
-+ if (is_preferred_input(selected_inputs, td.m_key_image) &&
-+ !is_spent(td, false) &&
-+ !td.m_frozen &&
-+ !td.m_key_image_partial &&
-+ td.m_key_image_known &&
-+ td.is_rct() &&
-+ is_transfer_unlocked(td) &&
-+ td.m_subaddr_index.major == index_major)
-+ {
-+ amount += td.m_amount;
-+ }
-+ }
-+ return amount;
-+}
-+//----------------------------------------------------------------------------------------------------
- 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;
-@@ -7889,9 +7918,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;
-
-- // compute public keys from out secret keys
-- crypto::public_key tx_pub_key;
-- crypto::secret_key_to_public_key(txs[n].tx_key, tx_pub_key);
-+ crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx);
- std::vector<crypto::public_key> additional_tx_pub_keys;
- for (const crypto::secret_key &skey: txs[n].additional_tx_keys)
- {
-@@ -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;
- }
-- if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
-+ if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && td.m_key_image_known && (use_rct ? true : !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)
- {
-@@ -11337,9 +11364,15 @@ 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");
-
-- if (unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty())
-- return std::vector<wallet2::pending_tx>();
-+ // use tobotoht's code path on view-only wallet, otherwise default to upstream
-+ bool throwOnNoEnotes = m_account.get_device().device_protocol() == hw::device::PROTOCOL_COLD || m_watch_only || m_multisig || m_is_background_wallet;
-
-+ if (throwOnNoEnotes) {
-+ THROW_WALLET_EXCEPTION_IF(unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty(), error::wallet_internal_error, "No enotes available to spend")
-+ } else {
-+ if (unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty())
-+ return std::vector<wallet2::pending_tx>();
-+ }
- // if empty, put dummy entry so that the front can be referenced later in the loop
- if (unused_dust_indices_per_subaddr.empty())
- unused_dust_indices_per_subaddr.push_back({});
-diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
-index 56cc118f4..b9aa7a00d 100644
---- a/src/wallet/wallet2.h
-+++ b/src/wallet/wallet2.h
-@@ -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);
-+ uint64_t view_only_balance(uint32_t index_major, const std::vector<crypto::key_image>& selected_inputs = {});
- // 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.39.2
-
diff --git a/patches/wownero/0014-store-crash-fix.patch b/patches/monero/0003-store-crash-fix.patch
index 8fa2eb0..225f0ab 100644
--- a/patches/wownero/0014-store-crash-fix.patch
+++ b/patches/monero/0003-store-crash-fix.patch
@@ -1,7 +1,7 @@
-From 462a261e97814d71b976fe04af26cda2637deb4f Mon Sep 17 00:00:00 2001
+From b49bc52f3d3d1751dd65d4694e4f74b84b23f583 Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Sat, 11 May 2024 16:25:10 +0200
-Subject: [PATCH 14/14] store crash fix
+Subject: [PATCH 03/14] store crash fix
Monero wallet crashes (sometimes) when it is syncing,
while the proper solution (that can be seen in feather)
@@ -38,15 +38,15 @@ the current state.
---
src/wallet/api/wallet.cpp | 25 ++++++++++++-------------
src/wallet/api/wallet.h | 1 -
- src/wallet/wallet2.cpp | 12 +++++++++++-
+ src/wallet/wallet2.cpp | 11 ++++++++++-
src/wallet/wallet2.h | 3 +++
- 4 files changed, 26 insertions(+), 15 deletions(-)
+ 4 files changed, 25 insertions(+), 15 deletions(-)
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index 02cf7c79b..b416c9535 100644
+index e9f76f4..0d85cf3 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
-@@ -57,8 +57,8 @@ using namespace cryptonote;
+@@ -55,8 +55,8 @@ using namespace cryptonote;
#define MONERO_DEFAULT_LOG_CATEGORY "WalletAPI"
#define LOCK_REFRESH() \
@@ -57,7 +57,7 @@ index 02cf7c79b..b416c9535 100644
m_wallet->stop(); \
m_refreshCV.notify_one(); \
boost::mutex::scoped_lock lock(m_refreshMutex); \
-@@ -468,7 +468,7 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds)
+@@ -466,7 +466,7 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds)
m_wallet2Callback.reset(new Wallet2CallbackImpl(this));
m_wallet->callback(m_wallet2Callback.get());
m_refreshThreadDone = false;
@@ -65,8 +65,8 @@ index 02cf7c79b..b416c9535 100644
+ m_wallet->set_refresh_enabled(false);
m_addressBook.reset(new AddressBookImpl(this));
m_subaddress.reset(new SubaddressImpl(this));
- m_coins.reset(new CoinsImpl(this));
-@@ -1092,6 +1092,7 @@ void WalletImpl::stop()
+ m_subaddressAccount.reset(new SubaddressAccountImpl(this));
+@@ -962,6 +962,7 @@ void WalletImpl::stop()
bool WalletImpl::store(const std::string &path)
{
clearStatus();
@@ -74,7 +74,7 @@ index 02cf7c79b..b416c9535 100644
try {
if (path.empty()) {
m_wallet->store();
-@@ -2877,10 +2878,10 @@ void WalletImpl::refreshThreadFunc()
+@@ -2448,10 +2449,10 @@ void WalletImpl::refreshThreadFunc()
}
LOG_PRINT_L3(__FUNCTION__ << ": refresh lock acquired...");
@@ -87,25 +87,22 @@ index 02cf7c79b..b416c9535 100644
LOG_PRINT_L3(__FUNCTION__ << ": refreshing...");
doRefresh();
}
-@@ -2912,7 +2913,7 @@ void WalletImpl::doRefresh()
+@@ -2481,12 +2482,12 @@ void WalletImpl::doRefresh()
}
m_wallet->find_and_save_rings(false);
} else {
- LOG_PRINT_L3(__FUNCTION__ << ": skipping refresh - daemon is not synced");
+ 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
-@@ -2925,7 +2926,7 @@ void WalletImpl::doRefresh()
- success = false;
+ } catch (const std::exception &e) {
setStatusError(e.what());
break;
- }while(!rescan && (rescan=m_refreshShouldRescan.exchange(false))); // repeat if not rescanned and rescan was requested
+ }while(m_wallet->get_refresh_enabled() && !rescan && (rescan=m_refreshShouldRescan.exchange(false))); // repeat if not rescanned and rescan was requested
- m_is_connected = success;
if (m_wallet2Callback->getListener()) {
-@@ -2936,9 +2937,9 @@ void WalletImpl::doRefresh()
+ m_wallet2Callback->getListener()->refreshed();
+@@ -2496,9 +2497,9 @@ void WalletImpl::doRefresh()
void WalletImpl::startRefresh()
{
@@ -117,7 +114,7 @@ index 02cf7c79b..b416c9535 100644
m_refreshCV.notify_one();
}
}
-@@ -2948,7 +2949,7 @@ void WalletImpl::startRefresh()
+@@ -2508,7 +2509,7 @@ void WalletImpl::startRefresh()
void WalletImpl::stopRefresh()
{
if (!m_refreshThreadDone) {
@@ -126,7 +123,7 @@ index 02cf7c79b..b416c9535 100644
m_refreshThreadDone = true;
m_refreshCV.notify_one();
m_refreshThread.join();
-@@ -2959,9 +2960,7 @@ void WalletImpl::pauseRefresh()
+@@ -2519,9 +2520,7 @@ void WalletImpl::pauseRefresh()
{
LOG_PRINT_L2(__FUNCTION__ << ": refresh paused...");
// TODO synchronize access
@@ -138,10 +135,10 @@ index 02cf7c79b..b416c9535 100644
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
-index 7b885e866..23d266de2 100644
+index 1f199a7..ac7ce2f 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
-@@ -325,7 +325,6 @@ private:
+@@ -273,7 +273,6 @@ private:
std::unique_ptr<SubaddressAccountImpl> m_subaddressAccount;
// multi-threaded refresh stuff
@@ -150,10 +147,10 @@ index 7b885e866..23d266de2 100644
std::atomic<int> m_refreshIntervalMillis;
std::atomic<bool> m_refreshShouldRescan;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
-index 4073974d9..0a0541cc8 100644
+index 8146014..7913d55 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
-@@ -1204,6 +1204,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
+@@ -1192,6 +1192,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
m_upper_transaction_weight_limit(0),
m_run(true),
m_callback(0),
@@ -161,7 +158,7 @@ index 4073974d9..0a0541cc8 100644
m_trusted_daemon(false),
m_nettype(nettype),
m_multisig_rounds_passed(0),
-@@ -1418,6 +1419,14 @@ bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_u
+@@ -1404,6 +1405,14 @@ bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_u
return ret;
}
//----------------------------------------------------------------------------------------------------
@@ -176,22 +173,20 @@ index 4073974d9..0a0541cc8 100644
bool wallet2::set_proxy(const std::string &address)
{
return m_http_client->set_proxy(address);
-@@ -4217,8 +4226,9 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
+@@ -4096,7 +4105,7 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
// infer when we get an incoming output
bool first = true, last = false;
- while(m_run.load(std::memory_order_relaxed) && blocks_fetched < max_blocks)
+ while(m_run.load(std::memory_order_relaxed) && blocks_fetched < max_blocks && m_refreshEnabled)
{
-+ LOG_ERROR("SYNCING");
uint64_t next_blocks_start_height;
std::vector<cryptonote::block_complete_entry> next_blocks;
- std::vector<parsed_block> next_parsed_blocks;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
-index d1e68baac..556306f20 100644
+index b1dc4f7..a050286 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
-@@ -1086,6 +1086,8 @@ private:
+@@ -1071,6 +1071,8 @@ private:
boost::optional<epee::net_utils::http::login> daemon_login = boost::none, bool trusted_daemon = true,
epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
bool set_proxy(const std::string &address);
@@ -200,7 +195,7 @@ index d1e68baac..556306f20 100644
void stop() { m_run.store(false, std::memory_order_relaxed); m_message_store.stop(); }
-@@ -2037,6 +2039,7 @@ private:
+@@ -1981,6 +1983,7 @@ private:
boost::recursive_mutex m_daemon_rpc_mutex;
@@ -209,5 +204,5 @@ index d1e68baac..556306f20 100644
i_wallet2_callback* m_callback;
hw::device::device_type m_key_device_type;
--
-2.45.2
+2.39.5 (Apple Git-154)
diff --git a/patches/wownero/0015-uint64_t-missing-definition-fix.patch b/patches/monero/0004-uint64_t-missing-definition-fix.patch
index e555829..129886b 100644
--- a/patches/wownero/0015-uint64_t-missing-definition-fix.patch
+++ b/patches/monero/0004-uint64_t-missing-definition-fix.patch
@@ -1,14 +1,14 @@
-From 9fe376e0024dfdbea47219477e797cb20c56305f Mon Sep 17 00:00:00 2001
+From 99e6af859234d8b37866e46d95d77e20687767de Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Mon, 2 Sep 2024 16:40:31 +0200
-Subject: [PATCH] uint64_t missing definition fix
+Subject: [PATCH 04/14] uint64_t missing definition fix
---
contrib/epee/include/net/http_base.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/contrib/epee/include/net/http_base.h b/contrib/epee/include/net/http_base.h
-index 4af4da790..ae4c0d05e 100644
+index 4af4da7..ae4c0d0 100644
--- a/contrib/epee/include/net/http_base.h
+++ b/contrib/epee/include/net/http_base.h
@@ -28,7 +28,7 @@
@@ -21,5 +21,5 @@ index 4af4da790..ae4c0d05e 100644
#include <string>
--
-2.43.0
+2.39.5 (Apple Git-154)
diff --git a/patches/monero/0005-fix-build-issues.patch b/patches/monero/0005-fix-build-issues.patch
deleted file mode 100644
index 985df3e..0000000
--- a/patches/monero/0005-fix-build-issues.patch
+++ /dev/null
@@ -1,137 +0,0 @@
-From 0f1d5e1296dc1e8c9ee323fa7bdf706ff76df2a7 Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Tue, 12 Mar 2024 17:59:13 +0100
-Subject: [PATCH 05/16] fix build issues
-
----
- contrib/depends/hosts/linux.mk | 8 +++----
- contrib/depends/packages/android_ndk.mk | 2 ++
- contrib/depends/packages/packages.mk | 2 +-
- contrib/depends/packages/polyseed.mk | 23 +++++++++++++++++++
- contrib/depends/packages/sodium.mk | 2 +-
- .../patches/polyseed/force-static-mingw.patch | 23 +++++++++++++++++++
- 6 files changed, 54 insertions(+), 6 deletions(-)
- create mode 100644 contrib/depends/packages/polyseed.mk
- create mode 100644 contrib/depends/patches/polyseed/force-static-mingw.patch
-
-diff --git a/contrib/depends/hosts/linux.mk b/contrib/depends/hosts/linux.mk
-index 912fdb03c..b79799f30 100644
---- a/contrib/depends/hosts/linux.mk
-+++ b/contrib/depends/hosts/linux.mk
-@@ -11,15 +11,15 @@ linux_debug_CXXFLAGS=$(linux_debug_CFLAGS)
- linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
-
- ifeq (86,$(findstring 86,$(build_arch)))
--i686_linux_CC=gcc -m32
--i686_linux_CXX=g++ -m32
-+i686_linux_CC=i686-linux-gnu-gcc
-+i686_linux_CXX=i686-linux-gnu-g++
- i686_linux_AR=ar
- i686_linux_RANLIB=ranlib
- i686_linux_NM=nm
- i686_linux_STRIP=strip
-
--x86_64_linux_CC=gcc -m64
--x86_64_linux_CXX=g++ -m64
-+x86_64_linux_CC=x86_64-linux-gnu-gcc
-+x86_64_linux_CXX=x86_64-linux-gnu-g++
- x86_64_linux_AR=ar
- x86_64_linux_RANLIB=ranlib
- x86_64_linux_NM=nm
-diff --git a/contrib/depends/packages/android_ndk.mk b/contrib/depends/packages/android_ndk.mk
-index 9b8a5332f..5deff76c7 100644
---- a/contrib/depends/packages/android_ndk.mk
-+++ b/contrib/depends/packages/android_ndk.mk
-@@ -7,6 +7,8 @@ $(package)_sha256_hash=5dfbbdc2d3ba859fed90d0e978af87c71a91a5be1f6e1c40ba697503d
- define $(package)_set_vars
- $(package)_config_opts_arm=--arch arm
- $(package)_config_opts_aarch64=--arch arm64
-+$(package)_config_opts_x86_64=--arch x86_64
-+$(package)_config_opts_i686=--arch x86
- endef
-
- define $(package)_extract_cmds
-diff --git a/contrib/depends/packages/packages.mk b/contrib/depends/packages/packages.mk
-index d2d1eca85..8783d4955 100644
---- a/contrib/depends/packages/packages.mk
-+++ b/contrib/depends/packages/packages.mk
-@@ -1,4 +1,4 @@
--packages:=boost openssl zeromq libiconv expat unbound
-+packages:=boost openssl zeromq libiconv expat unbound polyseed
-
- # ccache is useless in gitian builds
- ifneq ($(GITIAN),1)
-diff --git a/contrib/depends/packages/polyseed.mk b/contrib/depends/packages/polyseed.mk
-new file mode 100644
-index 000000000..2ddeac621
---- /dev/null
-+++ b/contrib/depends/packages/polyseed.mk
-@@ -0,0 +1,23 @@
-+package=polyseed
-+$(package)_version=2.0.0
-+$(package)_download_path=https://github.com/tevador/$(package)/archive/refs/tags/
-+$(package)_download_file=v$($(package)_version).tar.gz
-+$(package)_file_name=$(package)-$($(package)_version).tar.gz
-+$(package)_sha256_hash=f36282fcbcd68d32461b8230c89e1a40661bd46b91109681cec637433004135a
-+$(package)_patches=force-static-mingw.patch
-+
-+define $(package)_preprocess_cmds
-+ patch -p1 < $($(package)_patch_dir)/force-static-mingw.patch
-+endef
-+
-+define $(package)_config_cmds
-+ cmake -DCMAKE_INSTALL_PREFIX=$(host_prefix) -DCMAKE_C_COMPILER=$($(package)_cc) .
-+endef
-+
-+define $(package)_build_cmds
-+ $(MAKE)
-+endef
-+
-+define $(package)_stage_cmds
-+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
-+endef
-diff --git a/contrib/depends/packages/sodium.mk b/contrib/depends/packages/sodium.mk
-index 87b34599e..68a5b48ba 100644
---- a/contrib/depends/packages/sodium.mk
-+++ b/contrib/depends/packages/sodium.mk
-@@ -6,7 +6,7 @@ $(package)_sha256_hash=6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e
- $(package)_patches=disable-glibc-getrandom-getentropy.patch fix-whitespace.patch
-
- define $(package)_set_vars
--$(package)_config_opts=--enable-static --disable-shared
-+$(package)_config_opts=--enable-static --disable-shared --with-pic
- $(package)_config_opts+=--prefix=$(host_prefix)
- endef
-
-diff --git a/contrib/depends/patches/polyseed/force-static-mingw.patch b/contrib/depends/patches/polyseed/force-static-mingw.patch
-new file mode 100644
-index 000000000..f05cb2b6a
---- /dev/null
-+++ b/contrib/depends/patches/polyseed/force-static-mingw.patch
-@@ -0,0 +1,23 @@
-+--- a/include/polyseed.h
-++++ b/include/polyseed.h
-+@@ -93,13 +93,13 @@ Shared/static library definitions
-+ - define POLYSEED_STATIC when linking to the static library
-+ */
-+ #if defined(_WIN32) || defined(__CYGWIN__)
-+- #ifdef POLYSEED_SHARED
-+- #define POLYSEED_API __declspec(dllexport)
-+- #elif !defined(POLYSEED_STATIC)
-+- #define POLYSEED_API __declspec(dllimport)
-+- #else
-+- #define POLYSEED_API
-+- #endif
-++// #ifdef POLYSEED_SHARED
-++// #define POLYSEED_API __declspec(dllexport)
-++// #elif !defined(POLYSEED_STATIC)
-++// #define POLYSEED_API __declspec(dllimport)
-++// #else
-++ #define POLYSEED_API
-++// #endif
-+ #define POLYSEED_PRIVATE
-+ #else
-+ #ifdef POLYSEED_SHARED
---
-2.39.2
-
diff --git a/patches/wownero/0013-use-proper-error-handling-in-get_seed.patch b/patches/monero/0005-use-proper-error-handling-in-get_seed.patch
index ca98c84..3562b7b 100644
--- a/patches/wownero/0013-use-proper-error-handling-in-get_seed.patch
+++ b/patches/monero/0005-use-proper-error-handling-in-get_seed.patch
@@ -1,18 +1,18 @@
-From f813a27e5842afde721494b9a1038d8f9d00016b Mon Sep 17 00:00:00 2001
+From 6be87b2c75ea663e205f468c986809755839afa3 Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Mon, 24 Jun 2024 10:49:12 +0200
-Subject: [PATCH 13/14] use proper error handling in get_seed
+Subject: [PATCH 05/14] use proper error handling in get_seed
---
src/wallet/api/wallet.cpp | 17 ++++++++++++-----
- src/wallet/wallet2.cpp | 3 +++
- 2 files changed, 15 insertions(+), 5 deletions(-)
+ src/wallet/wallet2.cpp | 5 ++++-
+ 2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index ee0eeeb01..02cf7c79b 100644
+index 0d85cf3..dfbf4fd 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
-@@ -879,12 +879,19 @@ bool WalletImpl::close(bool store)
+@@ -826,12 +826,19 @@ bool WalletImpl::close(bool store)
std::string WalletImpl::seed(const std::string& seed_offset) const
{
@@ -36,12 +36,12 @@ index ee0eeeb01..02cf7c79b 100644
+ }
}
- bool WalletImpl::getPolyseed(std::string &seed_words, std::string &passphrase) const
+ std::string WalletImpl::getSeedLanguage() const
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
-index 2b3eaad2e..4073974d9 100644
+index 7913d55..debc0c2 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
-@@ -1445,11 +1445,13 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab
+@@ -1440,11 +1440,13 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab
bool keys_deterministic = is_deterministic();
if (!keys_deterministic)
{
@@ -55,14 +55,17 @@ index 2b3eaad2e..4073974d9 100644
std::cout << "seed_language not set" << std::endl;
return false;
}
-@@ -1459,6 +1461,7 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab
+@@ -1454,8 +1456,9 @@ 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))
{
+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, "Failed to create seed from key for language: "+seed_language+", falling back to English.");
- std::cout << "Failed to create seed from key for language: " << seed_language << ", falling back to English." << std::endl;
- crypto::ElectrumWords::bytes_to_words(key, electrum_words, "English");
+ std::cout << "Failed to create seed from key for language: " << seed_language << std::endl;
+- return false;
++ crypto::ElectrumWords::bytes_to_words(key, electrum_words, "English");
}
+
+ return true;
--
-2.45.2
+2.39.5 (Apple Git-154)
diff --git a/patches/monero/0012-WIP-UR-functions.patch b/patches/monero/0006-UR-functions.patch
index 564be97..c25b2d0 100644
--- a/patches/monero/0012-WIP-UR-functions.patch
+++ b/patches/monero/0006-UR-functions.patch
@@ -1,7 +1,7 @@
-From 1b938a3f98468de3fa06b21a458104cf32831586 Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Thu, 16 May 2024 17:28:59 +0200
-Subject: [PATCH 12/16] WIP: UR functions
+From 3138500cb65a6d72726d611d16cbd4b28d01fbe9 Mon Sep 17 00:00:00 2001
+From: tobtoht <tob@featherwallet.org>
+Date: Tue, 12 Mar 2024 10:09:50 +0100
+Subject: [PATCH 06/14] UR functions
This commit adds UR functions for UR tasks,
I believe that the right place to get
@@ -19,10 +19,8 @@ Things broken in the commit
later. However (considering the purpose
of this patch) it is not a dealbreaker.
---
- .gitmodules | 3 +
+ .gitmodules | 4 +
CMakeLists.txt | 4 +-
- contrib/depends/hosts/darwin.mk | 2 +-
- contrib/depends/toolchain.cmake.in | 2 +-
external/CMakeLists.txt | 1 +
external/bc-ur | 1 +
src/device/device_ledger.cpp | 5 +-
@@ -31,27 +29,28 @@ Things broken in the commit
src/wallet/api/pending_transaction.h | 1 +
src/wallet/api/unsigned_transaction.cpp | 42 ++++
src/wallet/api/unsigned_transaction.h | 1 +
- src/wallet/api/wallet.cpp | 286 +++++++++++++++++++++++-
- src/wallet/api/wallet.h | 6 +
- src/wallet/api/wallet2_api.h | 19 +-
- src/wallet/wallet2.cpp | 96 ++++----
- src/wallet/wallet2.h | 2 +
- 17 files changed, 452 insertions(+), 53 deletions(-)
+ src/wallet/api/wallet.cpp | 309 +++++++++++++++++++++++-
+ src/wallet/api/wallet.h | 8 +
+ src/wallet/api/wallet2_api.h | 22 +-
+ src/wallet/wallet2.cpp | 141 +++++++----
+ src/wallet/wallet2.h | 3 +
+ 15 files changed, 519 insertions(+), 57 deletions(-)
create mode 160000 external/bc-ur
diff --git a/.gitmodules b/.gitmodules
-index 7ea87a009..a7e1d2cd0 100644
+index ffb73fe..72af74d 100644
--- a/.gitmodules
+++ b/.gitmodules
-@@ -20,3 +20,6 @@
+@@ -15,3 +15,7 @@
path = external/supercop
url = https://github.com/monero-project/supercop
branch = monero
+[submodule "external/bc-ur"]
+ path = external/bc-ur
+ url = https://github.com/MrCyjaneK/bc-ur
++ branch = misc
diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 63b8c5079..6028c0961 100644
+index 8fb03ba..63ee825 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -96,7 +96,8 @@ enable_language(C ASM)
@@ -72,51 +71,25 @@ index 63b8c5079..6028c0961 100644
check_submodule(external/miniupnp)
check_submodule(external/rapidjson)
check_submodule(external/trezor-common)
-diff --git a/contrib/depends/hosts/darwin.mk b/contrib/depends/hosts/darwin.mk
-index cbe795081..b14ee5c5b 100644
---- a/contrib/depends/hosts/darwin.mk
-+++ b/contrib/depends/hosts/darwin.mk
-@@ -1,4 +1,4 @@
--OSX_MIN_VERSION=10.8
-+OSX_MIN_VERSION=10.14
- LD64_VERSION=609
- ifeq (aarch64, $(host_arch))
- CC_target=arm64-apple-$(host_os)
-diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in
-index f118c754e..f26655d68 100644
---- a/contrib/depends/toolchain.cmake.in
-+++ b/contrib/depends/toolchain.cmake.in
-@@ -94,7 +94,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
- SET(BREW OFF)
- SET(PORT OFF)
- SET(CMAKE_OSX_SYSROOT "@prefix@/native/SDK/")
-- SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.08")
-+ SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.14")
- SET(CMAKE_CXX_STANDARD 14)
- SET(LLVM_ENABLE_PIC OFF)
- SET(LLVM_ENABLE_PIE OFF)
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
-index 1b9761d70..0df9f9116 100644
+index 5b7f69a..f9ed6a6 100644
--- a/external/CMakeLists.txt
+++ b/external/CMakeLists.txt
-@@ -69,6 +69,7 @@ endif()
+@@ -69,4 +69,5 @@ endif()
add_subdirectory(db_drivers)
add_subdirectory(easylogging++)
add_subdirectory(qrcodegen)
+add_subdirectory(bc-ur)
add_subdirectory(randomx EXCLUDE_FROM_ALL)
- add_subdirectory(polyseed EXCLUDE_FROM_ALL)
- add_subdirectory(utf8proc EXCLUDE_FROM_ALL)
-\ No newline at end of file
diff --git a/external/bc-ur b/external/bc-ur
new file mode 160000
-index 000000000..d82e7c753
+index 0000000..d82e7c7
--- /dev/null
+++ b/external/bc-ur
@@ -0,0 +1 @@
+Subproject commit d82e7c753e710b8000706dc3383b498438795208
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
-index a4b5f3ef0..90675df11 100644
+index 5d0afe1..bb5b6f4 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -313,12 +313,13 @@ namespace hw {
@@ -136,7 +109,7 @@ index a4b5f3ef0..90675df11 100644
boost::lock_guard<boost::recursive_mutex> lock1(device_locker, boost::adopt_lock); \
boost::lock_guard<boost::mutex> lock2(command_locker, boost::adopt_lock)
diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt
-index 6095f99d5..b163212b7 100644
+index 6095f99..b163212 100644
--- a/src/wallet/CMakeLists.txt
+++ b/src/wallet/CMakeLists.txt
@@ -50,6 +50,7 @@ monero_add_library(wallet
@@ -148,7 +121,7 @@ index 6095f99d5..b163212b7 100644
common
cryptonote_core
diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp
-index be20b478c..1f714d229 100644
+index 70a7027..9c3c26e 100644
--- a/src/wallet/api/pending_transaction.cpp
+++ b/src/wallet/api/pending_transaction.cpp
@@ -42,6 +42,8 @@
@@ -160,7 +133,7 @@ index be20b478c..1f714d229 100644
using namespace std;
namespace Monero {
-@@ -178,6 +180,37 @@ bool PendingTransactionImpl::commit(const std::string &filename, bool overwrite)
+@@ -162,6 +164,37 @@ bool PendingTransactionImpl::commit(const std::string &filename, bool overwrite)
return m_status == Status_Ok;
}
@@ -199,7 +172,7 @@ index be20b478c..1f714d229 100644
{
uint64_t result = 0;
diff --git a/src/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h
-index 2fbaa83d9..0cc6c58e9 100644
+index 0a9779c..403bfe2 100644
--- a/src/wallet/api/pending_transaction.h
+++ b/src/wallet/api/pending_transaction.h
@@ -46,6 +46,7 @@ public:
@@ -211,7 +184,7 @@ index 2fbaa83d9..0cc6c58e9 100644
uint64_t dust() const override;
uint64_t fee() const override;
diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp
-index 6165a2240..fd03e959d 100644
+index 6165a22..fd03e95 100644
--- a/src/wallet/api/unsigned_transaction.cpp
+++ b/src/wallet/api/unsigned_transaction.cpp
@@ -40,6 +40,8 @@
@@ -271,7 +244,7 @@ index 6165a2240..fd03e959d 100644
bool UnsignedTransactionImpl::checkLoadedTx(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)
{
diff --git a/src/wallet/api/unsigned_transaction.h b/src/wallet/api/unsigned_transaction.h
-index 30065a7fa..a94b23f75 100644
+index 30065a7..a94b23f 100644
--- a/src/wallet/api/unsigned_transaction.h
+++ b/src/wallet/api/unsigned_transaction.h
@@ -53,6 +53,7 @@ public:
@@ -283,10 +256,10 @@ index 30065a7fa..a94b23f75 100644
uint64_t minMixinCount() const override;
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index 306c9b8ae..5ca190c7d 100644
+index dfbf4fd..4fb5f75 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
-@@ -48,6 +48,7 @@
+@@ -47,6 +47,7 @@
#include <boost/locale.hpp>
#include <boost/filesystem.hpp>
@@ -294,7 +267,32 @@ index 306c9b8ae..5ca190c7d 100644
using namespace std;
using namespace cryptonote;
-@@ -1321,6 +1322,61 @@ UnsignedTransaction *WalletImpl::loadUnsignedTx(const std::string &unsigned_file
+@@ -1066,6 +1067,24 @@ uint64_t WalletImpl::unlockedBalance(uint32_t accountIndex) const
+ return m_wallet->unlocked_balance(accountIndex, false);
+ }
+
++uint64_t WalletImpl::viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images) const
++{
++ clearStatus();
++
++ std::vector<crypto::key_image> kis;
++ for (const auto &key_image : key_images) {
++ crypto::key_image ki;
++ if (!epee::string_tools::hex_to_pod(key_image, ki))
++ {
++ setStatusError(tr("failed to parse key image"));
++ return 0;
++ }
++ kis.push_back(ki);
++ }
++
++ return m_wallet->view_only_balance(accountIndex, kis);
++}
++
+ uint64_t WalletImpl::blockChainHeight() const
+ {
+ if(m_wallet->light_wallet()) {
+@@ -1208,6 +1227,61 @@ UnsignedTransaction *WalletImpl::loadUnsignedTx(const std::string &unsigned_file
return transaction;
}
@@ -356,7 +354,7 @@ index 306c9b8ae..5ca190c7d 100644
bool WalletImpl::submitTransaction(const string &fileName) {
clearStatus();
if (checkBackgroundSync("cannot submit tx"))
-@@ -1332,7 +1388,7 @@ bool WalletImpl::submitTransaction(const string &fileName) {
+@@ -1219,7 +1293,7 @@ bool WalletImpl::submitTransaction(const string &fileName) {
setStatus(Status_Ok, tr("Failed to load transaction from file"));
return false;
}
@@ -365,7 +363,7 @@ index 306c9b8ae..5ca190c7d 100644
if(!transaction->commit()) {
setStatusError(transaction->m_errorString);
return false;
-@@ -1341,6 +1397,56 @@ bool WalletImpl::submitTransaction(const string &fileName) {
+@@ -1228,6 +1302,61 @@ bool WalletImpl::submitTransaction(const string &fileName) {
return true;
}
@@ -419,10 +417,15 @@ index 306c9b8ae..5ca190c7d 100644
+}
+
+
- bool WalletImpl::hasUnknownKeyImages() const
++bool WalletImpl::hasUnknownKeyImages() const
++{
++ return m_wallet->has_unknown_key_images();
++}
++
+ bool WalletImpl::exportKeyImages(const string &filename, bool all)
{
- return m_wallet->has_unknown_key_images();
-@@ -1373,6 +1479,39 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
+ if (m_wallet->watch_only())
+@@ -1255,6 +1384,39 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
return true;
}
@@ -462,7 +465,7 @@ index 306c9b8ae..5ca190c7d 100644
bool WalletImpl::importKeyImages(const string &filename)
{
if (checkBackgroundSync("cannot import key images"))
-@@ -1398,6 +1537,62 @@ bool WalletImpl::importKeyImages(const string &filename)
+@@ -1280,6 +1442,62 @@ bool WalletImpl::importKeyImages(const string &filename)
return true;
}
@@ -525,7 +528,7 @@ index 306c9b8ae..5ca190c7d 100644
bool WalletImpl::exportOutputs(const string &filename, bool all)
{
if (checkBackgroundSync("cannot export outputs"))
-@@ -1430,6 +1625,40 @@ bool WalletImpl::exportOutputs(const string &filename, bool all)
+@@ -1312,6 +1530,40 @@ bool WalletImpl::exportOutputs(const string &filename, bool all)
return true;
}
@@ -566,7 +569,7 @@ index 306c9b8ae..5ca190c7d 100644
bool WalletImpl::importOutputs(const string &filename)
{
if (checkBackgroundSync("cannot import outputs"))
-@@ -1464,6 +1693,61 @@ bool WalletImpl::importOutputs(const string &filename)
+@@ -1346,6 +1598,61 @@ bool WalletImpl::importOutputs(const string &filename)
return true;
}
@@ -629,17 +632,25 @@ index 306c9b8ae..5ca190c7d 100644
{
if (checkBackgroundSync("cannot scan transactions"))
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
-index 2ad2b62a4..febc93119 100644
+index ac7ce2f..edf8bb8 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
-@@ -182,12 +182,18 @@ public:
- const std::set<std::string> &preferred_inputs = {}) override;
+@@ -112,6 +112,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;
++ uint64_t viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images) const override;
+ uint64_t blockChainHeight() const override;
+ uint64_t approximateBlockChainHeight() const override;
+ uint64_t estimateBlockChainHeight() const override;
+@@ -164,11 +165,18 @@ public:
+ std::set<uint32_t> subaddr_indices = {}) override;
virtual PendingTransaction * createSweepUnmixableTransaction() override;
bool submitTransaction(const std::string &fileName) override;
+ bool submitTransactionUR(const std::string &input) override;
virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override;
+ virtual UnsignedTransaction * loadUnsignedTxUR(const std::string &input) override;
- bool hasUnknownKeyImages() const override;
++ bool hasUnknownKeyImages() const override;
bool exportKeyImages(const std::string &filename, bool all = false) override;
+ std::string exportKeyImagesUR(size_t max_fragment_length, bool all = false) override;
bool importKeyImages(const std::string &filename) override;
@@ -652,7 +663,7 @@ index 2ad2b62a4..febc93119 100644
bool setupBackgroundSync(const BackgroundSyncType background_sync_type, const std::string &wallet_password, const optional<std::string> &background_cache_password = optional<std::string>()) override;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
-index 1c3a11c39..2bbb32c8b 100644
+index e349df1..764adbf 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
@@ -91,6 +91,7 @@ struct PendingTransaction
@@ -663,7 +674,7 @@ index 1c3a11c39..2bbb32c8b 100644
virtual uint64_t amount() const = 0;
virtual uint64_t dust() const = 0;
virtual uint64_t fee() const = 0;
-@@ -162,7 +163,8 @@ struct UnsignedTransaction
+@@ -160,7 +161,8 @@ struct UnsignedTransaction
* @param signedFileName
* return - true on success
*/
@@ -673,7 +684,15 @@ index 1c3a11c39..2bbb32c8b 100644
};
/**
-@@ -938,13 +940,15 @@ struct Wallet
+@@ -626,6 +628,7 @@ struct Wallet
+ result += unlockedBalance(i);
+ return result;
+ }
++ virtual uint64_t viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images = {}) const = 0;
+
+ /**
+ * @brief watchOnly - checks if wallet is watch only
+@@ -884,13 +887,15 @@ struct Wallet
* after object returned
*/
virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) = 0;
@@ -692,7 +711,16 @@ index 1c3a11c39..2bbb32c8b 100644
/*!
* \brief disposeTransaction - destroys transaction object
-@@ -969,20 +973,22 @@ struct Wallet
+@@ -906,6 +911,8 @@ struct Wallet
+ virtual uint64_t estimateTransactionFee(const std::vector<std::pair<std::string, uint64_t>> &destinations,
+ PendingTransaction::Priority priority) const = 0;
+
++ virtual bool hasUnknownKeyImages() const = 0;
++
+ /*!
+ * \brief exportKeyImages - exports key images to file
+ * \param filename
+@@ -913,20 +920,22 @@ struct Wallet
* \return - true on success
*/
virtual bool exportKeyImages(const std::string &filename, bool all = false) = 0;
@@ -717,7 +745,7 @@ index 1c3a11c39..2bbb32c8b 100644
/*!
* \brief importOutputs - imports outputs from file
-@@ -990,6 +996,7 @@ struct Wallet
+@@ -934,6 +943,7 @@ struct Wallet
* \return - true on success
*/
virtual bool importOutputs(const std::string &filename) = 0;
@@ -726,10 +754,91 @@ index 1c3a11c39..2bbb32c8b 100644
/*!
* \brief scanTransactions - scan a list of transaction ids, this operation may reveal the txids to the remote node and affect your privacy
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
-index 4de226a4a..7d97e683b 100644
+index debc0c2..dfa3213 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
-@@ -14056,33 +14056,40 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle
+@@ -948,6 +948,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);
+@@ -6986,6 +6996,25 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t *
+ return amount;
+ }
+ //----------------------------------------------------------------------------------------------------
++uint64_t wallet2::view_only_balance(uint32_t index_major, const std::vector<crypto::key_image>& selected_inputs)
++{
++ uint64_t amount = 0;
++ for (const auto &td : m_transfers) {
++ if (is_preferred_input(selected_inputs, td.m_key_image) &&
++ !is_spent(td, false) &&
++ !td.m_frozen &&
++ !td.m_key_image_partial &&
++ td.m_key_image_known &&
++ td.is_rct() &&
++ is_transfer_unlocked(td) &&
++ td.m_subaddr_index.major == index_major)
++ {
++ amount += td.m_amount;
++ }
++ }
++ return amount;
++}
++//----------------------------------------------------------------------------------------------------
+ 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;
+@@ -7837,9 +7866,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;
+
+- // compute public keys from out secret keys
+- crypto::public_key tx_pub_key;
+- crypto::secret_key_to_public_key(txs[n].tx_key, tx_pub_key);
++ crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx);
+ std::vector<crypto::public_key> additional_tx_pub_keys;
+ for (const crypto::secret_key &skey: txs[n].additional_tx_keys)
+ {
+@@ -11235,7 +11262,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;
+ }
+- if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
++ if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && td.m_key_image_known && (use_rct ? true : !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)
+ {
+@@ -11285,9 +11312,15 @@ 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");
+
+- if (unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty())
+- return std::vector<wallet2::pending_tx>();
++ // use tobotoht's code path on view-only wallet, otherwise default to upstream
++ bool throwOnNoEnotes = m_account.get_device().device_protocol() == hw::device::PROTOCOL_COLD || m_watch_only || m_multisig || m_is_background_wallet;
+
++ if (throwOnNoEnotes) {
++ THROW_WALLET_EXCEPTION_IF(unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty(), error::wallet_internal_error, "No enotes available to spend")
++ } else {
++ if (unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty())
++ return std::vector<wallet2::pending_tx>();
++ }
+ // if empty, put dummy entry so that the front can be referenced later in the loop
+ if (unused_dust_indices_per_subaddr.empty())
+ unused_dust_indices_per_subaddr.push_back({});
+@@ -13923,33 +13956,40 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle
bool wallet2::export_key_images(const std::string &filename, bool all) const
{
@@ -763,7 +872,11 @@ index 4de226a4a..7d97e683b 100644
+ std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC));
+ const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
+ const uint32_t offset = ski.first;
-+
+
+- // encrypt data, keep magic plaintext
+- PERF_TIMER(export_key_images_encrypt);
+- std::string ciphertext = encrypt_with_view_secret_key(data);
+- return save_to_file(filename, magic + ciphertext);
+ std::string data;
+ data.reserve(4 + ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)) + 2 * sizeof(crypto::public_key));
+ data.resize(4);
@@ -778,11 +891,7 @@ index 4de226a4a..7d97e683b 100644
+ data += std::string((const char *)&i.first, sizeof(crypto::key_image));
+ data += std::string((const char *)&i.second, sizeof(crypto::signature));
+ }
-
-- // encrypt data, keep magic plaintext
-- PERF_TIMER(export_key_images_encrypt);
-- std::string ciphertext = encrypt_with_view_secret_key(data);
-- return save_to_file(filename, magic + ciphertext);
++
+ // encrypt data, keep magic plaintext
+ PERF_TIMER(export_key_images_encrypt);
+ std::string ciphertext = encrypt_with_view_secret_key(data);
@@ -793,7 +902,7 @@ index 4de226a4a..7d97e683b 100644
//----------------------------------------------------------------------------------------------------
std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> wallet2::export_key_images(bool all) const
{
-@@ -14137,53 +14144,60 @@ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>
+@@ -14004,53 +14044,60 @@ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>
return std::make_pair(offset, ski);
}
@@ -873,10 +982,18 @@ index 4de226a4a..7d97e683b 100644
ski.push_back(std::make_pair(key_image, signature));
}
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
-index 3ce710433..9ff169a40 100644
+index a050286..1d7e430 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
-@@ -1650,9 +1650,11 @@ private:
+@@ -1150,6 +1150,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);
++ uint64_t view_only_balance(uint32_t index_major, const std::vector<crypto::key_image>& selected_inputs = {});
+ // 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);
+@@ -1624,9 +1625,11 @@ private:
std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> export_blockchain() const;
void import_blockchain(const std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> &bc);
bool export_key_images(const std::string &filename, bool all = false) const;
@@ -889,5 +1006,5 @@ index 3ce710433..9ff169a40 100644
bool import_key_images(signed_tx_set & signed_tx, size_t offset=0, bool only_selected_transfers=false);
crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const;
--
-2.39.2
+2.39.5 (Apple Git-154)
diff --git a/patches/monero/0006-macos-build-fix.patch b/patches/monero/0006-macos-build-fix.patch
deleted file mode 100644
index f7c48b9..0000000
--- a/patches/monero/0006-macos-build-fix.patch
+++ /dev/null
@@ -1,114 +0,0 @@
-From 3343e3fbbd05546b3858c98afe3bad4673f250c8 Mon Sep 17 00:00:00 2001
-From: Your Name <you@example.com>
-Date: Thu, 28 Mar 2024 02:03:08 +0100
-Subject: [PATCH 06/16] macos build fix
-
----
- contrib/depends/hosts/darwin.mk | 2 +
- contrib/depends/packages/polyseed.mk | 13 +++--
- .../polyseed/0001-disable-soname.patch | 48 +++++++++++++++++++
- 3 files changed, 59 insertions(+), 4 deletions(-)
- create mode 100644 contrib/depends/patches/polyseed/0001-disable-soname.patch
-
-diff --git a/contrib/depends/hosts/darwin.mk b/contrib/depends/hosts/darwin.mk
-index 79d449054..cbe795081 100644
---- a/contrib/depends/hosts/darwin.mk
-+++ b/contrib/depends/hosts/darwin.mk
-@@ -8,6 +8,8 @@ endif
- darwin_CC=clang -target $(CC_target) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(host_prefix)/native/SDK/ -mlinker-version=$(LD64_VERSION) -B$(host_prefix)/native/bin/$(host)-
- darwin_CXX=clang++ -target $(CC_target) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(host_prefix)/native/SDK/ -mlinker-version=$(LD64_VERSION) -stdlib=libc++ -B$(host_prefix)/native/bin/$(host)-
-
-+darwin_RANLIB=$(host_prefix)/native/bin/$(host)-ranlib
-+
- darwin_CFLAGS=-pipe
- darwin_CXXFLAGS=$(darwin_CFLAGS)
- darwin_ARFLAGS=cr
-diff --git a/contrib/depends/packages/polyseed.mk b/contrib/depends/packages/polyseed.mk
-index 2ddeac621..0071b20f3 100644
---- a/contrib/depends/packages/polyseed.mk
-+++ b/contrib/depends/packages/polyseed.mk
-@@ -4,18 +4,23 @@ $(package)_download_path=https://github.com/tevador/$(package)/archive/refs/tags
- $(package)_download_file=v$($(package)_version).tar.gz
- $(package)_file_name=$(package)-$($(package)_version).tar.gz
- $(package)_sha256_hash=f36282fcbcd68d32461b8230c89e1a40661bd46b91109681cec637433004135a
--$(package)_patches=force-static-mingw.patch
-+$(package)_patches=force-static-mingw.patch 0001-disable-soname.patch
-
- define $(package)_preprocess_cmds
-- patch -p1 < $($(package)_patch_dir)/force-static-mingw.patch
-+ patch -p1 < $($(package)_patch_dir)/force-static-mingw.patch &&\
-+ patch -p1 < $($(package)_patch_dir)/0001-disable-soname.patch
- endef
-
- define $(package)_config_cmds
-- cmake -DCMAKE_INSTALL_PREFIX=$(host_prefix) -DCMAKE_C_COMPILER=$($(package)_cc) .
-+ CC="$($(package)_cc)" cmake -DCMAKE_INSTALL_PREFIX="$(host_prefix)" .
-+endef
-+
-+define $(package)_set_vars
-+ $(package)_build_opts=CC="$($(package)_cc)"
- endef
-
- define $(package)_build_cmds
-- $(MAKE)
-+ CC="$($(package)_cc)" $(MAKE)
- endef
-
- define $(package)_stage_cmds
-diff --git a/contrib/depends/patches/polyseed/0001-disable-soname.patch b/contrib/depends/patches/polyseed/0001-disable-soname.patch
-new file mode 100644
-index 000000000..bd97dd394
---- /dev/null
-+++ b/contrib/depends/patches/polyseed/0001-disable-soname.patch
-@@ -0,0 +1,48 @@
-+From aabafcfc0572651436d024a635483c49042fad7f Mon Sep 17 00:00:00 2001
-+From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-+Date: Thu, 28 Mar 2024 00:32:51 +0100
-+Subject: [PATCH] disable soname
-+
-+---
-+ CMakeLists.txt | 16 +++++++++-------
-+ 1 file changed, 9 insertions(+), 7 deletions(-)
-+
-+diff --git a/CMakeLists.txt b/CMakeLists.txt
-+index 8a8e7c2..5301353 100644
-+--- a/CMakeLists.txt
-++++ b/CMakeLists.txt
-+@@ -36,6 +36,7 @@ include_directories(polyseed
-+ target_compile_definitions(polyseed PRIVATE POLYSEED_SHARED)
-+ set_target_properties(polyseed PROPERTIES VERSION 2.0.0
-+ SOVERSION 2
-++ NO_SONAME 1
-+ C_STANDARD 11
-+ C_STANDARD_REQUIRED ON)
-+
-+@@ -45,16 +46,17 @@ include_directories(polyseed_static
-+ include/)
-+ target_compile_definitions(polyseed_static PRIVATE POLYSEED_STATIC)
-+ set_target_properties(polyseed_static PROPERTIES OUTPUT_NAME polyseed
-++ NO_SONAME 1
-+ C_STANDARD 11
-+ C_STANDARD_REQUIRED ON)
-+
-+-add_executable(polyseed-tests
-+- tests/tests.c)
-+-include_directories(polyseed-tests
-+- include/)
-+-target_compile_definitions(polyseed-tests PRIVATE POLYSEED_STATIC)
-+-target_link_libraries(polyseed-tests
-+- PRIVATE polyseed_static)
-++# add_executable(polyseed-tests
-++# tests/tests.c)
-++# include_directories(polyseed-tests
-++# include/)
-++# target_compile_definitions(polyseed-tests PRIVATE POLYSEED_STATIC)
-++# target_link_libraries(polyseed-tests
-++# PRIVATE polyseed_static)
-+
-+ include(GNUInstallDirs)
-+ install(TARGETS polyseed polyseed_static
-+--
-+2.39.2
---
-2.39.2
-
diff --git a/patches/monero/0007-add-dummy-device-for-ledger.patch b/patches/monero/0007-add-dummy-device-for-ledger.patch
new file mode 100644
index 0000000..b9e1bea
--- /dev/null
+++ b/patches/monero/0007-add-dummy-device-for-ledger.patch
@@ -0,0 +1,604 @@
+From bf8c0d01e60dade9fbdd77c4ce825e6b37d3c6c3 Mon Sep 17 00:00:00 2001
+From: Czarek Nakamoto <cyjan@mrcyjanek.net>
+Date: Wed, 26 Jun 2024 15:04:38 +0200
+Subject: [PATCH 07/14] add dummy device for ledger
+
+---
+ CMakeLists.txt | 6 +-
+ src/device/CMakeLists.txt | 6 +-
+ src/device/device.cpp | 10 ++-
+ src/device/device.hpp | 12 +--
+ src/device/device_io_dummy.cpp | 133 ++++++++++++++++++++++++++++++
+ src/device/device_io_dummy.hpp | 74 +++++++++++++++++
+ src/device/device_ledger.cpp | 6 +-
+ src/device/device_ledger.hpp | 7 +-
+ src/wallet/api/wallet.cpp | 94 +++++++++++++++++++++
+ src/wallet/api/wallet.h | 18 ++++
+ src/wallet/api/wallet2_api.h | 12 +++
+ src/wallet/api/wallet_manager.cpp | 12 ++-
+ 12 files changed, 365 insertions(+), 25 deletions(-)
+ create mode 100644 src/device/device_io_dummy.cpp
+ create mode 100644 src/device/device_io_dummy.hpp
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 63ee825..43ef6cd 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -692,8 +692,12 @@ include_directories(${LMDB_INCLUDE})
+ include_directories(${LIBUNWIND_INCLUDE})
+ link_directories(${LIBUNWIND_LIBRARY_DIRS})
+
++if (HIDAPI_DUMMY)
++ add_definitions(-DHIDAPI_DUMMY)
++endif()
++
+ # Final setup for hid
+-if (HIDAPI_FOUND)
++if (HIDAPI_FOUND)
+ message(STATUS "Using HIDAPI include dir at ${HIDAPI_INCLUDE_DIR}")
+ add_definitions(-DHAVE_HIDAPI)
+ include_directories(${HIDAPI_INCLUDE_DIR})
+diff --git a/src/device/CMakeLists.txt b/src/device/CMakeLists.txt
+index e4f1159..14d398f 100644
+--- a/src/device/CMakeLists.txt
++++ b/src/device/CMakeLists.txt
+@@ -29,10 +29,11 @@
+ set(device_sources
+ device.cpp
+ device_default.cpp
++ device_io_dummy.cpp
+ log.cpp
+ )
+
+-if(HIDAPI_FOUND)
++if(HIDAPI_FOUND OR HIDAPI_DUMMY)
+ set(device_sources
+ ${device_sources}
+ device_ledger.cpp
+@@ -45,10 +46,11 @@ set(device_headers
+ device_io.hpp
+ device_default.hpp
+ device_cold.hpp
++ device_io_dummy.hpp
+ log.hpp
+ )
+
+-if(HIDAPI_FOUND)
++if(HIDAPI_FOUND OR HIDAPI_DUMMY)
+ set(device_headers
+ ${device_headers}
+ device_ledger.hpp
+diff --git a/src/device/device.cpp b/src/device/device.cpp
+index e6cd358..777584c 100644
+--- a/src/device/device.cpp
++++ b/src/device/device.cpp
+@@ -29,7 +29,7 @@
+
+ #include "device.hpp"
+ #include "device_default.hpp"
+-#ifdef WITH_DEVICE_LEDGER
++#if defined(WITH_DEVICE_LEDGER) || defined(HIDAPI_DUMMY)
+ #include "device_ledger.hpp"
+ #endif
+ #include "misc_log_ex.h"
+@@ -57,7 +57,7 @@ namespace hw {
+
+ device_registry::device_registry(){
+ hw::core::register_all(registry);
+- #ifdef WITH_DEVICE_LEDGER
++ #if defined(WITH_DEVICE_LEDGER) && !defined(HIDAPI_DUMMY)
+ hw::ledger::register_all(registry);
+ #endif
+ atexit(clear_device_registry);
+@@ -83,11 +83,13 @@ namespace hw {
+
+ auto device = registry.find(device_descriptor_lookup);
+ if (device == registry.end()) {
+- MERROR("Device not found in registry: '" << device_descriptor << "'. Known devices: ");
++ std::stringstream ss("Device not found in registry: '" + device_descriptor + "'. Known devices: ");
++ MERROR("Device not found in registry: '" << device_descriptor << "'. Known devices: \n");
+ for( const auto& sm_pair : registry ) {
++ ss << "\n- " + sm_pair.first;
+ MERROR(" - " << sm_pair.first);
+ }
+- throw std::runtime_error("device not found: " + device_descriptor);
++ throw std::runtime_error("device not found: " + device_descriptor + "\nlalala\n" + ss.str());
+ }
+ return *device->second;
+ }
+diff --git a/src/device/device.hpp b/src/device/device.hpp
+index 392703a..ffd4197 100644
+--- a/src/device/device.hpp
++++ b/src/device/device.hpp
+@@ -34,17 +34,7 @@
+ #include "ringct/rctTypes.h"
+ #include "cryptonote_config.h"
+
+-
+-#ifndef USE_DEVICE_LEDGER
+-#define USE_DEVICE_LEDGER 1
+-#endif
+-
+-#if !defined(HAVE_HIDAPI)
+-#undef USE_DEVICE_LEDGER
+-#define USE_DEVICE_LEDGER 0
+-#endif
+-
+-#if USE_DEVICE_LEDGER
++#if defined(HAVE_HIDAPI) || defined(HIDAPI_DUMMY)
+ #define WITH_DEVICE_LEDGER
+ #endif
+
+diff --git a/src/device/device_io_dummy.cpp b/src/device/device_io_dummy.cpp
+new file mode 100644
+index 0000000..edb4bee
+--- /dev/null
++++ b/src/device/device_io_dummy.cpp
+@@ -0,0 +1,133 @@
++// Copyright (c) 2017-2022, The Monero Project
++//
++// All rights reserved.
++//
++// Redistribution and use in source and binary forms, with or without modification, are
++// permitted provided that the following conditions are met:
++//
++// 1. Redistributions of source code must retain the above copyright notice, this list of
++// conditions and the following disclaimer.
++//
++// 2. Redistributions in binary form must reproduce the above copyright notice, this list
++// of conditions and the following disclaimer in the documentation and/or other
++// materials provided with the distribution.
++//
++// 3. Neither the name of the copyright holder nor the names of its contributors may be
++// used to endorse or promote products derived from this software without specific
++// prior written permission.
++//
++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
++// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
++// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
++// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++//
++
++// device_io_dummy
++// Main goal of device_io_dummy is to emulate a hw::io::device_io without the need to actually
++// connect a device.
++// Many operating systems do not support giving raw USB access to a process (android), or don't
++// support that at all (hi iOS), therefore other means of connection can be used, either USB
++// abstraction provided by the OS (monerujo), or BLE (also monerujo).
++// Monerujo implementation is written in Java, which makes it a nice fit for iOS, but makes the
++// code extremely unportable, so for this reason the code in here is written in CPP.
++// Data transport is made available in wallet2_api.h, so wallet developers can easily plug their
++// own USB/BLE/other transport layer.
++
++#if defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI)
++#include <boost/scope_exit.hpp>
++#include "log.hpp"
++#include "device_io_dummy.hpp"
++#include "device_ledger.hpp"
++
++
++bool hw::io::device_io_dummy::stateIsConnected = false;
++unsigned char* hw::io::device_io_dummy::sendToDevice = {};
++size_t hw::io::device_io_dummy::sendToDeviceLength = 0;
++unsigned char* hw::io::device_io_dummy::receivedFromDevice = {};
++size_t hw::io::device_io_dummy::receivedFromDeviceLength = 0;
++bool hw::io::device_io_dummy::waitsForDeviceSend = false;
++bool hw::io::device_io_dummy::waitsForDeviceReceive = false;
++
++namespace hw {
++ namespace io {
++
++#undef MONERO_DEFAULT_LOG_CATEGORY
++#define MONERO_DEFAULT_LOG_CATEGORY "device.io_dummy"
++ device_io_dummy::device_io_dummy(int a, int b, int c, int d) {
++ MDEBUG("device_io_dummy(a: " << a << ", b: " << b << ", c: " << c << ", d: " << d <<")");
++ }
++
++ void device_io_dummy::init() {
++ MDEBUG("init()");
++ }
++
++ void device_io_dummy::connect(void *params) {
++ MDEBUG("connect(" << params << ")");
++ stateIsConnected = true;
++ }
++
++ void device_io_dummy::connect(const std::vector<hw::io::hid_conn_params>& known_devices) {
++ MDEBUG("connect([");
++ for (const auto &item: known_devices) {
++ MDEBUG("{ interface_number: " << item.interface_number);
++ MDEBUG(" pid : " << item.pid);
++ MDEBUG(" usage_page : " << item.usage_page);
++ MDEBUG(" vid : " << item.vid << " },");
++ }
++ MDEBUG("])");
++ stateIsConnected = true;
++ }
++
++ bool device_io_dummy::connected() const {
++ MDEBUG("connected()");
++ return stateIsConnected;
++ }
++
++ int device_io_dummy::exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input) {
++ MDEBUG("exchange(): locking mutex");
++ boost::unique_lock<boost::mutex> lock(mutex);
++ sendToDevice = command;
++ sendToDeviceLength = cmd_len;
++ waitsForDeviceSend = true;
++ waitsForDeviceReceive = true;
++ MDEBUG("exchange(): waitsForDeviceSend");
++ // NOTE: waitsForDeviceSend should be changed by external code
++ while (waitsForDeviceSend) {
++ usleep(1000);
++ MDEBUG("exchange(): waitsForDeviceSend (still)");
++ }
++
++ MDEBUG("exchange(): waitsForDeviceReceive");
++ while (waitsForDeviceReceive) {
++ usleep(1000);
++ MDEBUG("exchange(): waitsForDeviceReceive (still)");
++ }
++
++ if (receivedFromDeviceLength > max_resp_len) {
++ MDEBUG("exchange(): receivedFromDeviceLength ("<<receivedFromDeviceLength<<") is larger than max_resp_len ("<<max_resp_len<<")");
++ return 1;
++ }
++
++ memset(response,0,max_resp_len);
++ memcpy(response, receivedFromDevice, receivedFromDeviceLength);
++ return receivedFromDeviceLength;
++ }
++
++ void device_io_dummy::disconnect() {
++ MDEBUG("disconnect()");
++ }
++
++ void device_io_dummy::release() {
++ MDEBUG("release()");
++ }
++
++
++
++ }
++}
++#endif // HAVE_HIDAPI
+\ No newline at end of file
+diff --git a/src/device/device_io_dummy.hpp b/src/device/device_io_dummy.hpp
+new file mode 100644
+index 0000000..a173361
+--- /dev/null
++++ b/src/device/device_io_dummy.hpp
+@@ -0,0 +1,74 @@
++// Copyright (c) 2017-2022, The Monero Project
++//
++// All rights reserved.
++//
++// Redistribution and use in source and binary forms, with or without modification, are
++// permitted provided that the following conditions are met:
++//
++// 1. Redistributions of source code must retain the above copyright notice, this list of
++// conditions and the following disclaimer.
++//
++// 2. Redistributions in binary form must reproduce the above copyright notice, this list
++// of conditions and the following disclaimer in the documentation and/or other
++// materials provided with the distribution.
++//
++// 3. Neither the name of the copyright holder nor the names of its contributors may be
++// used to endorse or promote products derived from this software without specific
++// prior written permission.
++//
++// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
++// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
++// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
++// THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
++// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
++// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
++// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
++// STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
++// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
++//
++#ifdef HIDAPI_DUMMY
++
++#pragma once
++
++#include "device_io.hpp"
++#include "device_io_hid.hpp"
++
++namespace hw {
++ namespace io {
++ struct hid_conn_params {
++ unsigned int vid;
++ unsigned int pid;
++ int interface_number;
++ unsigned short usage_page;
++ };
++ class device_io_dummy : device_io {
++ private:
++ boost::mutex mutex;
++
++ public:
++ static bool stateIsConnected;
++ static unsigned char* sendToDevice;
++ static size_t sendToDeviceLength;
++ static unsigned char* receivedFromDevice;
++ static size_t receivedFromDeviceLength;
++ static bool waitsForDeviceSend;
++ static bool waitsForDeviceReceive;
++
++ device_io_dummy() = default;
++ device_io_dummy(int a, int b, int c, int d);
++ ~device_io_dummy() = default;
++
++ void init();
++ void release();
++
++ void connect(void *parms);
++ void connect(const std::vector<hw::io::hid_conn_params>& known_devices);
++ void disconnect();
++ bool connected() const;
++
++ int exchange(unsigned char *command, unsigned int cmd_len, unsigned char *response, unsigned int max_resp_len, bool user_input);
++ };
++ };
++};
++
++#endif // HAVE_HIDAPI
+diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
+index bb5b6f4..046201a 100644
+--- a/src/device/device_ledger.cpp
++++ b/src/device/device_ledger.cpp
+@@ -41,7 +41,7 @@ namespace hw {
+
+ namespace ledger {
+
+- #ifdef WITH_DEVICE_LEDGER
++ #if defined(WITH_DEVICE_LEDGER) || defined(HIDAPI_DUMMY)
+
+ #undef MONERO_DEFAULT_LOG_CATEGORY
+ #define MONERO_DEFAULT_LOG_CATEGORY "device.ledger"
+@@ -299,7 +299,7 @@ namespace hw {
+
+ device_ledger::device_ledger(): hw_device(0x0101, 0x05, 64, 2000) {
+ this->id = device_id++;
+- this->reset_buffer();
++ this->reset_buffer();
+ this->mode = NONE;
+ this->has_view_key = false;
+ this->tx_in_progress = false;
+@@ -533,7 +533,9 @@ namespace hw {
+
+ bool device_ledger::connect(void) {
+ this->disconnect();
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
+ hw_device.connect(known_devices);
++ #endif
+ this->reset();
+ #ifdef DEBUG_HWDEVICE
+ cryptonote::account_public_address pubkey;
+diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
+index 03058c4..39454ca 100644
+--- a/src/device/device_ledger.hpp
++++ b/src/device/device_ledger.hpp
+@@ -35,6 +35,7 @@
+ #include "device.hpp"
+ #include "log.hpp"
+ #include "device_io_hid.hpp"
++#include "device_io_dummy.hpp"
+ #include <boost/thread/mutex.hpp>
+ #include <boost/thread/recursive_mutex.hpp>
+
+@@ -56,7 +57,7 @@ namespace hw {
+
+ void register_all(std::map<std::string, std::unique_ptr<device>> &registry);
+
+- #ifdef WITH_DEVICE_LEDGER
++ #if defined(WITH_DEVICE_LEDGER) || defined(HIDAPI_DUMMY)
+
+ // Origin: https://github.com/LedgerHQ/ledger-app-monero/blob/master/src/monero_types.h
+ #define SW_OK 0x9000
+@@ -148,7 +149,11 @@ namespace hw {
+ mutable boost::mutex command_locker;
+
+ //IO
++#if defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI)
++ hw::io::device_io_dummy hw_device;
++#else
+ hw::io::device_io_hid hw_device;
++#endif
+ unsigned int length_send;
+ unsigned char buffer_send[BUFFER_SEND_SIZE];
+ unsigned int length_recv;
+diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
+index 4fb5f75..c73f38e 100644
+--- a/src/wallet/api/wallet.cpp
++++ b/src/wallet/api/wallet.cpp
+@@ -48,6 +48,9 @@
+ #include <boost/locale.hpp>
+ #include <boost/filesystem.hpp>
+ #include "bc-ur/src/bc-ur.hpp"
++#if defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI)
++#include "device/device_io_dummy.hpp"
++#endif
+
+ using namespace std;
+ using namespace cryptonote;
+@@ -3178,4 +3181,95 @@ uint64_t WalletImpl::getBytesSent()
+ return m_wallet->get_bytes_sent();
+ }
+
++
++// HIDAPI_DUMMY
++bool WalletImpl::getStateIsConnected() {
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
++ return false;
++ #else
++ return hw::io::device_io_dummy::stateIsConnected;
++ #endif
++}
++
++unsigned char* WalletImpl::getSendToDevice() {
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
++ return {};
++ #else
++ return hw::io::device_io_dummy::sendToDevice;
++ #endif
++}
++
++size_t WalletImpl::getSendToDeviceLength() {
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
++ return -1;
++ #else
++ return hw::io::device_io_dummy::sendToDeviceLength;
++ #endif
++}
++
++unsigned char* WalletImpl::getReceivedFromDevice() {
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
++ return {};
++ #else
++ return hw::io::device_io_dummy::receivedFromDevice;
++ #endif
++}
++
++size_t WalletImpl::getReceivedFromDeviceLength() {
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
++ return -1;
++ #else
++ return hw::io::device_io_dummy::receivedFromDeviceLength;
++ #endif
++}
++
++bool WalletImpl::getWaitsForDeviceSend() {
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
++ return false;
++ #else
++ return hw::io::device_io_dummy::receivedFromDeviceLength;
++ #endif
++}
++
++bool WalletImpl::getWaitsForDeviceReceive() {
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
++ return false;
++ #else
++ return hw::io::device_io_dummy::waitsForDeviceReceive;
++ #endif
++}
++
++void WalletImpl::setDeviceReceivedData(unsigned char* data, size_t len) {
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
++ return;
++ #else
++ hw::io::device_io_dummy::receivedFromDevice = static_cast<unsigned char *>(malloc(len));
++ hw::io::device_io_dummy::receivedFromDeviceLength = len;
++ memset(hw::io::device_io_dummy::receivedFromDevice, 0, len);
++ memcpy(hw::io::device_io_dummy::receivedFromDevice, data, len);
++ hw::io::device_io_dummy::waitsForDeviceReceive = false;
++ #endif
++}
++
++void WalletImpl::setDeviceSendData(unsigned char* data, size_t len) {
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
++ return;
++ #else
++ hw::io::device_io_dummy::sendToDevice = static_cast<unsigned char *>(malloc(len));
++ hw::io::device_io_dummy::sendToDeviceLength = len;
++ memset(hw::io::device_io_dummy::sendToDevice, 0, len);
++ memcpy(hw::io::device_io_dummy::sendToDevice, data, len);
++ hw::io::device_io_dummy::waitsForDeviceSend = false;
++ #endif
++}
++
+ } // namespace
+diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
+index edf8bb8..4e9c21e 100644
+--- a/src/wallet/api/wallet.h
++++ b/src/wallet/api/wallet.h
+@@ -301,6 +301,24 @@ private:
+ // cache connection status to avoid unnecessary RPC calls
+ mutable std::atomic<bool> m_is_connected;
+ boost::optional<epee::net_utils::http::login> m_daemon_login{};
++
++ bool getStateIsConnected();
++
++ unsigned char *getSendToDevice();
++
++ size_t getSendToDeviceLength();
++
++ unsigned char *getReceivedFromDevice();
++
++ size_t getReceivedFromDeviceLength();
++
++ bool getWaitsForDeviceSend();
++
++ bool getWaitsForDeviceReceive();
++
++ void setDeviceReceivedData(unsigned char *data, size_t len);
++
++ void setDeviceSendData(unsigned char *data, size_t len);
+ };
+
+
+diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
+index 764adbf..53ec4ab 100644
+--- a/src/wallet/api/wallet2_api.h
++++ b/src/wallet/api/wallet2_api.h
+@@ -1150,6 +1150,18 @@ struct Wallet
+
+ //! get bytes sent
+ virtual uint64_t getBytesSent() = 0;
++
++ // HIDAPI_DUMMY
++ virtual bool getStateIsConnected() = 0;
++ virtual unsigned char* getSendToDevice() = 0;
++ virtual size_t getSendToDeviceLength() = 0;
++ virtual unsigned char* getReceivedFromDevice() = 0;
++ virtual size_t getReceivedFromDeviceLength() = 0;
++ virtual bool getWaitsForDeviceSend() = 0;
++ virtual bool getWaitsForDeviceReceive() = 0;
++
++ virtual void setDeviceReceivedData(unsigned char* data, size_t len) = 0;
++ virtual void setDeviceSendData(unsigned char* data, size_t len) = 0;
+ };
+
+ /**
+diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
+index e81b8f8..277be6a 100644
+--- a/src/wallet/api/wallet_manager.cpp
++++ b/src/wallet/api/wallet_manager.cpp
+@@ -188,10 +188,14 @@ bool WalletManagerImpl::verifyWalletPassword(const std::string &keys_file_name,
+
+ bool WalletManagerImpl::queryWalletDevice(Wallet::Device& device_type, const std::string &keys_file_name, const std::string &password, uint64_t kdf_rounds) const
+ {
+- hw::device::device_type type;
+- bool r = tools::wallet2::query_device(type, keys_file_name, password, kdf_rounds);
+- device_type = static_cast<Wallet::Device>(type);
+- return r;
++ try {
++ hw::device::device_type type;
++ bool r = tools::wallet2::query_device(type, keys_file_name, password, kdf_rounds);
++ device_type = static_cast<Wallet::Device>(type);
++ return r;
++ } catch (...) {
++ return false;
++ }
+ }
+
+ std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)
+--
+2.39.5 (Apple Git-154)
+
diff --git a/patches/monero/0007-fix-make-debug-test-target.patch b/patches/monero/0007-fix-make-debug-test-target.patch
deleted file mode 100644
index f39c49e..0000000
--- a/patches/monero/0007-fix-make-debug-test-target.patch
+++ /dev/null
@@ -1,39 +0,0 @@
-From 8945e9865ef831f85ef58ba3d269f4b17d0270b5 Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Tue, 2 Apr 2024 01:13:12 +0200
-Subject: [PATCH 07/16] fix `make debug-test` target
-
----
- src/simplewallet/simplewallet.cpp | 2 +-
- src/wallet/wallet2.h | 2 +-
- 2 files changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
-index f8ed6659c..0aa76b668 100644
---- a/src/simplewallet/simplewallet.cpp
-+++ b/src/simplewallet/simplewallet.cpp
-@@ -6929,7 +6929,7 @@ bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool ca
- {
- // figure out what tx will be necessary
- auto ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, priority, extra,
-- m_current_subaddress_account, subaddr_indices, subtract_fee_from_outputs);
-+ m_current_subaddress_account, subaddr_indices, {}, subtract_fee_from_outputs);
-
- if (ptx_vector.empty())
- {
-diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
-index 67ed81383..fdc1a6212 100644
---- a/src/wallet/wallet2.h
-+++ b/src/wallet/wallet2.h
-@@ -1207,7 +1207,7 @@ private:
- bool parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsigned_tx_set &exported_txs) const;
- bool load_tx(const std::string &signed_filename, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set&)> accept_func = NULL);
- bool parse_tx_from_str(const std::string &signed_tx_st, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set &)> accept_func);
-- std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list, const unique_index_container& subtract_fee_from_outputs = {}); // pass subaddr_indices by value on purpose
-+ std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list = {}, const unique_index_container& subtract_fee_from_outputs = {}); // pass subaddr_indices by value on purpose
- std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list = {});
- 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, 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, uint32_t priority, const std::vector<uint8_t>& extra);
---
-2.39.2
-
diff --git a/patches/monero/0001-polyseed.patch b/patches/monero/0008-polyseed.patch
index 8164403..9289fc0 100644
--- a/patches/monero/0001-polyseed.patch
+++ b/patches/monero/0008-polyseed.patch
@@ -1,7 +1,7 @@
-From 8324040dfb89bd90b414ea685b2aa758a461fbc4 Mon Sep 17 00:00:00 2001
+From ed2ce176ea5f1bbe81069a3df4601a141b533b95 Mon Sep 17 00:00:00 2001
From: tobtoht <tob@featherwallet.org>
Date: Tue, 12 Mar 2024 09:42:37 +0100
-Subject: [PATCH 01/16] polyseed
+Subject: [PATCH 08/14] polyseed
Co-authored-by: Czarek Nakamoto <cyjan@mrcyjanek.net>
---
@@ -10,6 +10,8 @@ Co-authored-by: Czarek Nakamoto <cyjan@mrcyjanek.net>
contrib/epee/include/wipeable_string.h | 7 +
contrib/epee/src/wipeable_string.cpp | 10 ++
external/CMakeLists.txt | 2 +
+ external/polyseed | 1 +
+ external/utf8proc | 1 +
src/CMakeLists.txt | 1 +
src/cryptonote_basic/CMakeLists.txt | 1 +
src/cryptonote_basic/account.cpp | 23 +++-
@@ -20,14 +22,16 @@ Co-authored-by: Czarek Nakamoto <cyjan@mrcyjanek.net>
src/polyseed/pbkdf2.h | 46 +++++++
src/polyseed/polyseed.cpp | 182 +++++++++++++++++++++++++
src/polyseed/polyseed.hpp | 167 +++++++++++++++++++++++
- src/wallet/api/wallet.cpp | 71 ++++++++++
+ src/wallet/api/wallet.cpp | 70 ++++++++++
src/wallet/api/wallet.h | 10 ++
src/wallet/api/wallet2_api.h | 25 ++++
src/wallet/api/wallet_manager.cpp | 9 ++
src/wallet/api/wallet_manager.h | 10 ++
- src/wallet/wallet2.cpp | 102 ++++++++++++--
+ src/wallet/wallet2.cpp | 100 ++++++++++++--
src/wallet/wallet2.h | 30 +++-
- 22 files changed, 805 insertions(+), 19 deletions(-)
+ 24 files changed, 805 insertions(+), 18 deletions(-)
+ create mode 160000 external/polyseed
+ create mode 160000 external/utf8proc
create mode 100644 src/polyseed/CMakeLists.txt
create mode 100644 src/polyseed/pbkdf2.c
create mode 100644 src/polyseed/pbkdf2.h
@@ -35,13 +39,13 @@ Co-authored-by: Czarek Nakamoto <cyjan@mrcyjanek.net>
create mode 100644 src/polyseed/polyseed.hpp
diff --git a/.gitmodules b/.gitmodules
-index 721cce3b4..73a23fb35 100644
+index 72af74d..b838e84 100644
--- a/.gitmodules
+++ b/.gitmodules
-@@ -10,6 +10,12 @@
- [submodule "external/randomx"]
+@@ -11,6 +11,12 @@
path = external/randomx
- url = https://github.com/tevador/RandomX
+ url = https://github.com/MrCyjaneK/RandomX
+ branch = cyjan-fix-ios
+[submodule "external/utf8proc"]
+ path = external/utf8proc
+ url = https://github.com/JuliaStrings/utf8proc.git
@@ -52,10 +56,10 @@ index 721cce3b4..73a23fb35 100644
path = external/supercop
url = https://github.com/monero-project/supercop
diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 8fb03ba1f..63b8c5079 100644
+index 43ef6cd..e7fa90a 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
-@@ -369,6 +369,8 @@ if(NOT MANUAL_SUBMODULES)
+@@ -371,6 +371,8 @@ if(NOT MANUAL_SUBMODULES)
check_submodule(external/trezor-common)
check_submodule(external/randomx)
check_submodule(external/supercop)
@@ -64,7 +68,7 @@ index 8fb03ba1f..63b8c5079 100644
endif()
endif()
-@@ -458,7 +460,7 @@ endif()
+@@ -460,7 +462,7 @@ endif()
# elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSDI.*")
# set(BSDI TRUE)
@@ -74,7 +78,7 @@ index 8fb03ba1f..63b8c5079 100644
if(APPLE)
cmake_policy(SET CMP0042 NEW)
diff --git a/contrib/epee/include/wipeable_string.h b/contrib/epee/include/wipeable_string.h
-index 65977cd97..594e15de4 100644
+index 65977cd..594e15d 100644
--- a/contrib/epee/include/wipeable_string.h
+++ b/contrib/epee/include/wipeable_string.h
@@ -34,6 +34,7 @@
@@ -99,7 +103,7 @@ index 65977cd97..594e15de4 100644
private:
void grow(size_t sz, size_t reserved = 0);
diff --git a/contrib/epee/src/wipeable_string.cpp b/contrib/epee/src/wipeable_string.cpp
-index b016f2f48..f2f365b1b 100644
+index b016f2f..f2f365b 100644
--- a/contrib/epee/src/wipeable_string.cpp
+++ b/contrib/epee/src/wipeable_string.cpp
@@ -261,4 +261,14 @@ wipeable_string &wipeable_string::operator=(const wipeable_string &other)
@@ -118,18 +122,33 @@ index b016f2f48..f2f365b1b 100644
+
}
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
-index 5b7f69a56..1b9761d70 100644
+index f9ed6a6..8fcf792 100644
--- a/external/CMakeLists.txt
+++ b/external/CMakeLists.txt
-@@ -70,3 +70,5 @@ add_subdirectory(db_drivers)
+@@ -69,5 +69,7 @@ endif()
+ add_subdirectory(db_drivers)
add_subdirectory(easylogging++)
add_subdirectory(qrcodegen)
- add_subdirectory(randomx EXCLUDE_FROM_ALL)
+add_subdirectory(polyseed EXCLUDE_FROM_ALL)
+add_subdirectory(utf8proc EXCLUDE_FROM_ALL)
-\ No newline at end of file
+ add_subdirectory(bc-ur)
+ add_subdirectory(randomx EXCLUDE_FROM_ALL)
+diff --git a/external/polyseed b/external/polyseed
+new file mode 160000
+index 0000000..bd79f50
+--- /dev/null
++++ b/external/polyseed
+@@ -0,0 +1 @@
++Subproject commit bd79f5014c331273357277ed8a3d756fb61b9fa1
+diff --git a/external/utf8proc b/external/utf8proc
+new file mode 160000
+index 0000000..3de4596
+--- /dev/null
++++ b/external/utf8proc
+@@ -0,0 +1 @@
++Subproject commit 3de4596fbe28956855df2ecb3c11c0bbc3535838
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
-index 3335d3c21..06b708cf0 100644
+index 3335d3c..06b708c 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -95,6 +95,7 @@ add_subdirectory(net)
@@ -141,7 +160,7 @@ index 3335d3c21..06b708cf0 100644
if(NOT IOS)
add_subdirectory(serialization)
diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt
-index 1414be1b2..414936a05 100644
+index 1414be1..414936a 100644
--- a/src/cryptonote_basic/CMakeLists.txt
+++ b/src/cryptonote_basic/CMakeLists.txt
@@ -71,6 +71,7 @@ target_link_libraries(cryptonote_basic
@@ -153,7 +172,7 @@ index 1414be1b2..414936a05 100644
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_SERIALIZATION_LIBRARY}
diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp
-index 2ac455fda..4931c3740 100644
+index 4e87d44..2d556f2 100644
--- a/src/cryptonote_basic/account.cpp
+++ b/src/cryptonote_basic/account.cpp
@@ -87,12 +87,16 @@ DISABLE_VS_WARNINGS(4244 4345)
@@ -182,8 +201,8 @@ index 2ac455fda..4931c3740 100644
+ m_keys.m_passphrase.wipe();
}
//-----------------------------------------------------------------
- crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random)
-@@ -244,6 +250,21 @@ DISABLE_VS_WARNINGS(4244 4345)
+ void account_base::set_spend_key(const crypto::secret_key& spend_secret_key)
+@@ -255,6 +261,21 @@ DISABLE_VS_WARNINGS(4244 4345)
create_from_keys(address, fake, viewkey);
}
//-----------------------------------------------------------------
@@ -206,7 +225,7 @@ index 2ac455fda..4931c3740 100644
{
m_keys.m_account_address.m_spend_public_key = spend_public_key;
diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h
-index 2ee9545d4..0099ebfe7 100644
+index 93d1d28..1f76feb 100644
--- a/src/cryptonote_basic/account.h
+++ b/src/cryptonote_basic/account.h
@@ -33,6 +33,7 @@
@@ -244,7 +263,7 @@ 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 f9e6a6c..3af3a63 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -207,6 +207,8 @@
@@ -258,7 +277,7 @@ index 61146a114..8e1a07110 100644
// (1+32) + (1+1+16*32) + (1+16*32) = 1060
diff --git a/src/polyseed/CMakeLists.txt b/src/polyseed/CMakeLists.txt
new file mode 100644
-index 000000000..cca4eb746
+index 0000000..cca4eb7
--- /dev/null
+++ b/src/polyseed/CMakeLists.txt
@@ -0,0 +1,25 @@
@@ -289,7 +308,7 @@ index 000000000..cca4eb746
+)
diff --git a/src/polyseed/pbkdf2.c b/src/polyseed/pbkdf2.c
new file mode 100644
-index 000000000..1c45f4708
+index 0000000..1c45f47
--- /dev/null
+++ b/src/polyseed/pbkdf2.c
@@ -0,0 +1,85 @@
@@ -381,7 +400,7 @@ index 000000000..1c45f4708
\ No newline at end of file
diff --git a/src/polyseed/pbkdf2.h b/src/polyseed/pbkdf2.h
new file mode 100644
-index 000000000..f6253b9d7
+index 0000000..f6253b9
--- /dev/null
+++ b/src/polyseed/pbkdf2.h
@@ -0,0 +1,46 @@
@@ -434,7 +453,7 @@ index 000000000..f6253b9d7
\ No newline at end of file
diff --git a/src/polyseed/polyseed.cpp b/src/polyseed/polyseed.cpp
new file mode 100644
-index 000000000..231a48a94
+index 0000000..231a48a
--- /dev/null
+++ b/src/polyseed/polyseed.cpp
@@ -0,0 +1,182 @@
@@ -622,7 +641,7 @@ index 000000000..231a48a94
+}
diff --git a/src/polyseed/polyseed.hpp b/src/polyseed/polyseed.hpp
new file mode 100644
-index 000000000..2c8c777a7
+index 0000000..2c8c777
--- /dev/null
+++ b/src/polyseed/polyseed.hpp
@@ -0,0 +1,167 @@
@@ -795,10 +814,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 fc4f89128..d96ea97ea 100644
+index c73f38e..67ac90a 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
+@@ -728,6 +728,28 @@ bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &p
return true;
}
@@ -827,35 +846,35 @@ index fc4f89128..d96ea97ea 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
- return std::string(seed.data(), seed.size()); // TODO
+@@ -845,6 +867,54 @@ std::string WalletImpl::seed(const std::string& seed_offset) const
+ }
}
+bool WalletImpl::getPolyseed(std::string &seed_words, std::string &passphrase) const
+{
-+ epee::wipeable_string seed_words_epee(seed_words.c_str(), seed_words.size());
-+ epee::wipeable_string passphrase_epee(passphrase.c_str(), passphrase.size());
-+ clearStatus();
++ epee::wipeable_string seed_words_epee(seed_words.c_str(), seed_words.size());
++ epee::wipeable_string passphrase_epee(passphrase.c_str(), passphrase.size());
++ clearStatus();
+
-+ if (!m_wallet) {
-+ return false;
-+ }
++ if (!m_wallet) {
++ return false;
++ }
+
-+ bool result = m_wallet->get_polyseed(seed_words_epee, passphrase_epee);
++ 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());
++ seed_words.assign(seed_words_epee.data(), seed_words_epee.size());
++ passphrase.assign(passphrase_epee.data(), passphrase_epee.size());
+
-+ return result;
++ return result;
+}
+
+std::vector<std::pair<std::string, std::string>> Wallet::getPolyseedLanguages()
-+{
++ {
+ std::vector<std::pair<std::string, std::string>> languages;
+
+ auto langs = polyseed::get_langs();
+ for (const auto &lang : langs) {
-+ languages.emplace_back(std::pair<std::string, std::string>(lang.name_en(), lang.name()));
++ languages.emplace_back(std::pair<std::string, std::string>(lang.name_en(), lang.name()));
+ }
+
+ return languages;
@@ -863,28 +882,27 @@ index fc4f89128..d96ea97ea 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());
++ epee::wipeable_string seed_words_epee(seed_words.c_str(), seed_words.size());
+
-+ try {
-+ polyseed::data polyseed(POLYSEED_COIN);
-+ polyseed.create(0);
-+ polyseed.encode(polyseed::get_lang_by_name(language), seed_words_epee);
++ try {
++ polyseed::data polyseed(POLYSEED_COIN);
++ polyseed.create(0);
++ polyseed.encode(polyseed::get_lang_by_name(language), seed_words_epee);
+
-+ seed_words.assign(seed_words_epee.data(), seed_words_epee.size());
-+ }
-+ catch (const std::exception &e) {
-+ err = e.what();
-+ return false;
-+ }
++ seed_words.assign(seed_words_epee.data(), seed_words_epee.size());
++ }
++ catch (const std::exception &e) {
++ err = e.what();
++ return false;
++ }
+
-+ return true;
++ return true;
+}
-+
std::string WalletImpl::getSeedLanguage() const
{
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 4e9c21e..32e1228 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -79,9 +79,19 @@ public:
@@ -908,10 +926,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 53ec4ab..be1c370 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
-@@ -700,6 +700,10 @@ struct Wallet
+@@ -709,6 +709,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);
@@ -922,7 +940,7 @@ index 71991df0d..9ea753083 100644
/**
* @brief StartRefresh - Start/resume refresh thread (refresh every 10 seconds)
*/
-@@ -1256,6 +1260,27 @@ struct WalletManager
+@@ -1320,6 +1324,27 @@ struct WalletManager
uint64_t kdf_rounds = 1,
WalletListener * listener = nullptr) = 0;
@@ -951,7 +969,7 @@ 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 277be6a..da2056d 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,
@@ -971,7 +989,7 @@ 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 a223e1d..28fcd36 100644
--- a/src/wallet/api/wallet_manager.h
+++ b/src/wallet/api/wallet_manager.h
@@ -75,6 +75,16 @@ public:
@@ -992,7 +1010,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 64f486e71..9e95f44d6 100644
+index dfa3213..fa346a9 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -92,6 +92,7 @@ using namespace epee;
@@ -1003,7 +1021,7 @@ index 64f486e71..9e95f44d6 100644
extern "C"
{
-@@ -1260,7 +1261,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
+@@ -1278,7 +1279,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),
@@ -1013,61 +1031,56 @@ index 64f486e71..9e95f44d6 100644
{
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
- key = cryptonote::encrypt_key(key, passphrase);
- if (!crypto::ElectrumWords::bytes_to_words(key, electrum_words, seed_language))
- {
-- std::cout << "Failed to create seed from key for language: " << seed_language << std::endl;
-+ std::cout << "Failed to create seed from key for language: " << seed_language << ", falling back to English." << std::endl;
-+ crypto::ElectrumWords::bytes_to_words(key, electrum_words, "English");
-+ }
+@@ -1474,6 +1476,20 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab
+ return true;
+ }
+ //----------------------------------------------------------------------------------------------------
+
-+ return true;
-+}
-+//----------------------------------------------------------------------------------------------------
+bool wallet2::get_polyseed(epee::wipeable_string& polyseed, epee::wipeable_string& passphrase) const
+{
+ if (!m_polyseed) {
- return false;
- }
-
++ return false;
++ }
++
+ polyseed::data data(POLYSEED_COIN);
+ data.load(get_account().get_keys().m_polyseed);
+ data.encode(polyseed::get_lang_by_name(seed_language), polyseed);
-+
+ passphrase = get_account().get_keys().m_passphrase;
-+
- return true;
- }
- //----------------------------------------------------------------------------------------------------
-@@ -4630,6 +4647,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
++ return true;
++}
++//----------------------------------------------------------------------------------------------------
+ bool wallet2::get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase) const
+ {
+ bool ready;
+@@ -4789,6 +4805,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const crypt
value2.SetInt(m_enable_multisig ? 1 : 0);
json.AddMember("enable_multisig", value2, json.GetAllocator());
+ value2.SetInt(m_polyseed ? 1 : 0);
+ json.AddMember("polyseed", value2, json.GetAllocator());
+
- // Serialize the JSON object
- rapidjson::StringBuffer buffer;
- rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
-@@ -4777,6 +4797,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
- m_credits_target = 0;
+ 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());
+@@ -5028,6 +5047,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;
}
else if(json.IsObject())
{
-@@ -5013,6 +5034,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;
+@@ -5268,6 +5288,9 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, background_sync_type, BackgroundSyncType, Int, false, BackgroundSyncOff);
+ m_background_sync_type = field_background_sync_type;
+
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, polyseed, int, Int, false, false);
+ m_polyseed = field_polyseed;
- }
- else
- {
-@@ -5285,6 +5308,48 @@ void wallet2::init_type(hw::device::device_type device_type)
++
+ // Load encryption key used to encrypt background cache
+ crypto::chacha_key custom_background_key;
+ m_custom_background_key = boost::none;
+@@ -5587,6 +5610,48 @@ void wallet2::init_type(hw::device::device_type device_type)
m_key_device_type = device_type;
}
@@ -1116,7 +1129,7 @@ index 64f486e71..9e95f44d6 100644
/*!
* \brief Generates a wallet or restores one. Assumes the multisig setup
* has already completed for the provided multisig info.
-@@ -5412,7 +5477,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
+@@ -5714,7 +5779,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
return retval;
}
@@ -1125,7 +1138,7 @@ index 64f486e71..9e95f44d6 100644
{
// -1 month for fluctuations in block time and machine date/time setup.
// avg seconds per block
-@@ -5436,7 +5501,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
+@@ -5738,7 +5803,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.
@@ -1134,7 +1147,7 @@ index 64f486e71..9e95f44d6 100644
uint64_t target_height = get_daemon_blockchain_target_height(err);
if (err.empty()) {
if (target_height < height)
-@@ -13133,7 +13198,7 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err)
+@@ -13635,7 +13700,7 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err)
return target_height;
}
@@ -1143,7 +1156,7 @@ index 64f486e71..9e95f44d6 100644
{
// time of v2 fork
const time_t fork_time = m_nettype == TESTNET ? 1448285909 : m_nettype == STAGENET ? 1520937818 : 1458748658;
-@@ -13142,7 +13207,7 @@ uint64_t wallet2::get_approximate_blockchain_height() const
+@@ -13644,7 +13709,7 @@ uint64_t wallet2::get_approximate_blockchain_height() const
// avg seconds per block
const int seconds_per_block = DIFFICULTY_TARGET_V2;
// Calculated blockchain height
@@ -1152,7 +1165,7 @@ index 64f486e71..9e95f44d6 100644
// 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 : m_nettype == STAGENET ? 60000 : 30000;
if ((m_nettype == TESTNET || m_nettype == STAGENET) && approx_blockchain_height > approximate_rolled_back_blocks)
-@@ -14860,15 +14925,6 @@ bool wallet2::parse_uri(const std::string &uri, std::string &address, std::strin
+@@ -15783,15 +15848,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)
{
@@ -1168,7 +1181,7 @@ index 64f486e71..9e95f44d6 100644
std::tm date = { 0, 0, 0, 0, 0, 0, 0, 0 };
date.tm_year = year - 1900;
date.tm_mon = month - 1;
-@@ -14877,7 +14933,23 @@ uint64_t wallet2::get_blockchain_height_by_date(uint16_t year, uint8_t month, ui
+@@ -15800,7 +15856,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");
}
@@ -1193,7 +1206,7 @@ index 64f486e71..9e95f44d6 100644
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 c38d77675..91ec72e0f 100644
+index 1d7e430..91cf2a3 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -72,6 +72,7 @@
@@ -1204,7 +1217,7 @@ index c38d77675..91ec72e0f 100644
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2"
-@@ -854,6 +855,20 @@ private:
+@@ -921,6 +922,20 @@ private:
void generate(const std::string& wallet_, const epee::wipeable_string& password,
const epee::wipeable_string& multisig_data, bool create_address_file = false);
@@ -1225,7 +1238,7 @@ index c38d77675..91ec72e0f 100644
/*!
* \brief Generates a wallet or restores one.
* \param wallet_ Name of wallet file
-@@ -1018,6 +1033,15 @@ private:
+@@ -1088,6 +1103,15 @@ private:
bool is_deterministic() const;
bool get_seed(epee::wipeable_string& electrum_words, const epee::wipeable_string &passphrase = epee::wipeable_string()) const;
@@ -1241,7 +1254,7 @@ index c38d77675..91ec72e0f 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:
+@@ -1555,8 +1579,8 @@ private:
/*!
* \brief Calculates the approximate blockchain height from current date/time.
*/
@@ -1252,7 +1265,7 @@ index c38d77675..91ec72e0f 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:
+@@ -1650,6 +1674,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
@@ -1260,7 +1273,7 @@ index c38d77675..91ec72e0f 100644
bool is_synced();
-@@ -1874,6 +1899,7 @@ private:
+@@ -1995,6 +2020,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 */
@@ -1269,5 +1282,5 @@ index c38d77675..91ec72e0f 100644
uint32_t m_multisig_threshold;
std::vector<crypto::public_key> m_multisig_signers;
--
-2.39.2
+2.39.5 (Apple Git-154)
diff --git a/patches/monero/0009-coin-control.patch b/patches/monero/0009-coin-control.patch
new file mode 100644
index 0000000..1aac12a
--- /dev/null
+++ b/patches/monero/0009-coin-control.patch
@@ -0,0 +1,979 @@
+From 4d897d9ee1d24710500f4d58e9ccd79fb48cf1d2 Mon Sep 17 00:00:00 2001
+From: tobtoht <tob@featherwallet.org>
+Date: Tue, 12 Mar 2024 11:07:57 +0100
+Subject: [PATCH 09/14] coin control
+
+---
+ src/simplewallet/simplewallet.cpp | 2 +-
+ src/wallet/api/CMakeLists.txt | 8 +-
+ src/wallet/api/coins.cpp | 186 ++++++++++++++++++++++++++++++
+ src/wallet/api/coins.h | 40 +++++++
+ src/wallet/api/coins_info.cpp | 122 ++++++++++++++++++++
+ src/wallet/api/coins_info.h | 71 ++++++++++++
+ src/wallet/api/wallet.cpp | 64 +++++++++-
+ src/wallet/api/wallet.h | 10 +-
+ src/wallet/api/wallet2_api.h | 52 ++++++++-
+ src/wallet/wallet2.cpp | 46 +++++++-
+ src/wallet/wallet2.h | 11 +-
+ 11 files changed, 593 insertions(+), 19 deletions(-)
+ create mode 100644 src/wallet/api/coins.cpp
+ create mode 100644 src/wallet/api/coins.h
+ create mode 100644 src/wallet/api/coins_info.cpp
+ create mode 100644 src/wallet/api/coins_info.h
+
+diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
+index 2c51337..645bd37 100644
+--- a/src/simplewallet/simplewallet.cpp
++++ b/src/simplewallet/simplewallet.cpp
+@@ -6930,7 +6930,7 @@ bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool ca
+ {
+ // figure out what tx will be necessary
+ auto ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, priority, extra,
+- m_current_subaddress_account, subaddr_indices, subtract_fee_from_outputs);
++ m_current_subaddress_account, subaddr_indices, {}, subtract_fee_from_outputs);
+
+ if (ptx_vector.empty())
+ {
+diff --git a/src/wallet/api/CMakeLists.txt b/src/wallet/api/CMakeLists.txt
+index af7948d..bb740e2 100644
+--- a/src/wallet/api/CMakeLists.txt
++++ b/src/wallet/api/CMakeLists.txt
+@@ -40,7 +40,9 @@ set(wallet_api_sources
+ address_book.cpp
+ subaddress.cpp
+ subaddress_account.cpp
+- unsigned_transaction.cpp)
++ unsigned_transaction.cpp
++ coins.cpp
++ coins_info.cpp)
+
+ set(wallet_api_headers
+ wallet2_api.h)
+@@ -55,7 +57,9 @@ set(wallet_api_private_headers
+ address_book.h
+ subaddress.h
+ subaddress_account.h
+- unsigned_transaction.h)
++ unsigned_transaction.h
++ coins.h
++ coins_info.h)
+
+ monero_private_headers(wallet_api
+ ${wallet_api_private_headers})
+diff --git a/src/wallet/api/coins.cpp b/src/wallet/api/coins.cpp
+new file mode 100644
+index 0000000..ef12141
+--- /dev/null
++++ b/src/wallet/api/coins.cpp
+@@ -0,0 +1,186 @@
++#include "coins.h"
++#include "coins_info.h"
++#include "wallet.h"
++#include "crypto/hash.h"
++#include "wallet/wallet2.h"
++#include "common_defines.h"
++
++#include <string>
++#include <vector>
++
++using namespace epee;
++
++namespace Monero {
++
++Coins::~Coins() = default;
++
++CoinsImpl::CoinsImpl(WalletImpl *wallet)
++ : m_wallet(wallet) {}
++
++CoinsImpl::~CoinsImpl()
++{
++ for (auto t : m_rows)
++ delete t;
++}
++
++int CoinsImpl::count() const
++{
++ boost::shared_lock<boost::shared_mutex> lock(m_rowsMutex);
++ int result = m_rows.size();
++ return result;
++}
++
++CoinsInfo *CoinsImpl::coin(int index) const
++{
++ boost::shared_lock<boost::shared_mutex> lock(m_rowsMutex);
++ // sanity check
++ if (index < 0)
++ return nullptr;
++ auto index_ = static_cast<unsigned>(index);
++ return index_ < m_rows.size() ? m_rows[index_] : nullptr;
++}
++
++std::vector<CoinsInfo *> CoinsImpl::getAll() const
++{
++ boost::shared_lock<boost::shared_mutex> lock(m_rowsMutex);
++ return m_rows;
++}
++
++
++void CoinsImpl::refresh()
++{
++ LOG_PRINT_L2("Refreshing coins");
++
++ boost::unique_lock<boost::shared_mutex> lock(m_rowsMutex);
++ boost::shared_lock<boost::shared_mutex> transfers_lock(m_wallet->m_wallet->m_transfers_mutex);
++
++ // delete old outputs;
++ for (auto t : m_rows)
++ delete t;
++ m_rows.clear();
++
++ for (size_t i = 0; i < m_wallet->m_wallet->get_num_transfer_details(); ++i)
++ {
++ const tools::wallet2::transfer_details &td = m_wallet->m_wallet->get_transfer_details(i);
++
++ auto ci = new CoinsInfoImpl();
++ ci->m_blockHeight = td.m_block_height;
++ ci->m_hash = string_tools::pod_to_hex(td.m_txid);
++ ci->m_internalOutputIndex = td.m_internal_output_index;
++ ci->m_globalOutputIndex = td.m_global_output_index;
++ ci->m_spent = td.m_spent;
++ ci->m_frozen = td.m_frozen;
++ ci->m_spentHeight = td.m_spent_height;
++ ci->m_amount = td.m_amount;
++ ci->m_rct = td.m_rct;
++ ci->m_keyImageKnown = td.m_key_image_known;
++ ci->m_pkIndex = td.m_pk_index;
++ ci->m_subaddrIndex = td.m_subaddr_index.minor;
++ ci->m_subaddrAccount = td.m_subaddr_index.major;
++ ci->m_address = m_wallet->m_wallet->get_subaddress_as_str(td.m_subaddr_index); // todo: this is expensive, cache maybe?
++ ci->m_addressLabel = m_wallet->m_wallet->get_subaddress_label(td.m_subaddr_index);
++ ci->m_keyImage = string_tools::pod_to_hex(td.m_key_image);
++ ci->m_unlockTime = td.m_tx.unlock_time;
++ ci->m_unlocked = m_wallet->m_wallet->is_transfer_unlocked(td);
++ ci->m_pubKey = string_tools::pod_to_hex(td.get_public_key());
++ ci->m_coinbase = td.m_tx.vin.size() == 1 && td.m_tx.vin[0].type() == typeid(cryptonote::txin_gen);
++ ci->m_description = m_wallet->m_wallet->get_tx_note(td.m_txid);
++
++ m_rows.push_back(ci);
++ }
++}
++
++void CoinsImpl::setFrozen(std::string public_key)
++{
++ crypto::public_key pk;
++ if (!epee::string_tools::hex_to_pod(public_key, pk))
++ {
++ LOG_ERROR("Invalid public key: " << public_key);
++ return;
++ }
++
++ try
++ {
++ m_wallet->m_wallet->freeze(pk);
++ refresh();
++ }
++ catch (const std::exception& e)
++ {
++ LOG_ERROR("setFrozen: " << e.what());
++ }
++}
++
++void CoinsImpl::setFrozen(int index)
++{
++ try
++ {
++ LOG_ERROR("Freezing coin: " << index);
++ m_wallet->m_wallet->freeze(index);
++ refresh();
++ }
++ catch (const std::exception& e)
++ {
++ LOG_ERROR("setLabel: " << e.what());
++ }
++}
++
++void CoinsImpl::thaw(std::string public_key)
++{
++ crypto::public_key pk;
++ if (!epee::string_tools::hex_to_pod(public_key, pk))
++ {
++ LOG_ERROR("Invalid public key: " << public_key);
++ return;
++ }
++
++ try
++ {
++ m_wallet->m_wallet->thaw(pk);
++ refresh();
++ }
++ catch (const std::exception& e)
++ {
++ LOG_ERROR("thaw: " << e.what());
++ }
++}
++
++void CoinsImpl::thaw(int index)
++{
++ try
++ {
++ m_wallet->m_wallet->thaw(index);
++ refresh();
++ }
++ catch (const std::exception& e)
++ {
++ LOG_ERROR("thaw: " << e.what());
++ }
++}
++
++bool CoinsImpl::isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) {
++ return m_wallet->m_wallet->is_transfer_unlocked(unlockTime, blockHeight);
++}
++
++void CoinsImpl::setDescription(const std::string &public_key, const std::string &description)
++{
++ crypto::public_key pk;
++ if (!epee::string_tools::hex_to_pod(public_key, pk))
++ {
++ LOG_ERROR("Invalid public key: " << public_key);
++ return;
++ }
++
++ try
++ {
++ const size_t index = m_wallet->m_wallet->get_transfer_details(pk);
++ const tools::wallet2::transfer_details &td = m_wallet->m_wallet->get_transfer_details(index);
++ m_wallet->m_wallet->set_tx_note(td.m_txid, description);
++ refresh();
++ }
++ catch (const std::exception& e)
++ {
++ LOG_ERROR("setDescription: " << e.what());
++ }
++}
++
++} // namespace
+diff --git a/src/wallet/api/coins.h b/src/wallet/api/coins.h
+new file mode 100644
+index 0000000..b7a0a86
+--- /dev/null
++++ b/src/wallet/api/coins.h
+@@ -0,0 +1,40 @@
++#ifndef FEATHER_COINS_H
++#define FEATHER_COINS_H
++
++#include "wallet/api/wallet2_api.h"
++#include "wallet/wallet2.h"
++
++namespace Monero {
++
++class WalletImpl;
++
++class CoinsImpl : public Coins
++{
++public:
++ explicit CoinsImpl(WalletImpl * wallet);
++ ~CoinsImpl() override;
++ int count() const override;
++ CoinsInfo * coin(int index) const override;
++ std::vector<CoinsInfo*> getAll() const override;
++ void refresh() override;
++
++ void setFrozen(std::string public_key) override;
++ void setFrozen(int index) override;
++ void thaw(std::string public_key) override;
++ void thaw(int index) override;
++
++ bool isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) override;
++
++ void setDescription(const std::string &public_key, const std::string &description) override;
++
++private:
++ WalletImpl *m_wallet;
++ std::vector<CoinsInfo*> m_rows;
++ mutable boost::shared_mutex m_rowsMutex;
++};
++
++}
++
++namespace Bitmonero = Monero;
++
++#endif //FEATHER_COINS_H
+diff --git a/src/wallet/api/coins_info.cpp b/src/wallet/api/coins_info.cpp
+new file mode 100644
+index 0000000..5f2c4e1
+--- /dev/null
++++ b/src/wallet/api/coins_info.cpp
+@@ -0,0 +1,122 @@
++#include "coins_info.h"
++
++using namespace std;
++
++namespace Monero {
++
++CoinsInfo::~CoinsInfo() = default;
++
++CoinsInfoImpl::CoinsInfoImpl()
++ : m_blockHeight(0)
++ , m_internalOutputIndex(0)
++ , m_globalOutputIndex(0)
++ , m_spent(false)
++ , m_frozen(false)
++ , m_spentHeight(0)
++ , m_amount(0)
++ , m_rct(false)
++ , m_keyImageKnown(false)
++ , m_pkIndex(0)
++ , m_subaddrAccount(0)
++ , m_subaddrIndex(0)
++ , m_unlockTime(0)
++ , m_unlocked(false)
++{
++
++}
++
++CoinsInfoImpl::~CoinsInfoImpl() = default;
++
++uint64_t CoinsInfoImpl::blockHeight() const
++{
++ return m_blockHeight;
++}
++
++string CoinsInfoImpl::hash() const
++{
++ return m_hash;
++}
++
++size_t CoinsInfoImpl::internalOutputIndex() const {
++ return m_internalOutputIndex;
++}
++
++uint64_t CoinsInfoImpl::globalOutputIndex() const
++{
++ return m_globalOutputIndex;
++}
++
++bool CoinsInfoImpl::spent() const
++{
++ return m_spent;
++}
++
++bool CoinsInfoImpl::frozen() const
++{
++ return m_frozen;
++}
++
++uint64_t CoinsInfoImpl::spentHeight() const
++{
++ return m_spentHeight;
++}
++
++uint64_t CoinsInfoImpl::amount() const
++{
++ return m_amount;
++}
++
++bool CoinsInfoImpl::rct() const {
++ return m_rct;
++}
++
++bool CoinsInfoImpl::keyImageKnown() const {
++ return m_keyImageKnown;
++}
++
++size_t CoinsInfoImpl::pkIndex() const {
++ return m_pkIndex;
++}
++
++uint32_t CoinsInfoImpl::subaddrIndex() const {
++ return m_subaddrIndex;
++}
++
++uint32_t CoinsInfoImpl::subaddrAccount() const {
++ return m_subaddrAccount;
++}
++
++string CoinsInfoImpl::address() const {
++ return m_address;
++}
++
++string CoinsInfoImpl::addressLabel() const {
++ return m_addressLabel;
++}
++
++string CoinsInfoImpl::keyImage() const {
++ return m_keyImage;
++}
++
++uint64_t CoinsInfoImpl::unlockTime() const {
++ return m_unlockTime;
++}
++
++bool CoinsInfoImpl::unlocked() const {
++ return m_unlocked;
++}
++
++string CoinsInfoImpl::pubKey() const {
++ return m_pubKey;
++}
++
++bool CoinsInfoImpl::coinbase() const {
++ return m_coinbase;
++}
++
++string CoinsInfoImpl::description() const {
++ return m_description;
++}
++} // namespace
++
++namespace Bitmonero = Monero;
+diff --git a/src/wallet/api/coins_info.h b/src/wallet/api/coins_info.h
+new file mode 100644
+index 0000000..c43e45a
+--- /dev/null
++++ b/src/wallet/api/coins_info.h
+@@ -0,0 +1,71 @@
++#ifndef FEATHER_COINS_INFO_H
++#define FEATHER_COINS_INFO_H
++
++#include "wallet/api/wallet2_api.h"
++#include <string>
++#include <ctime>
++
++namespace Monero {
++
++class CoinsImpl;
++
++class CoinsInfoImpl : public CoinsInfo
++{
++public:
++ CoinsInfoImpl();
++ ~CoinsInfoImpl();
++
++ virtual uint64_t blockHeight() const override;
++ virtual std::string hash() const override;
++ virtual size_t internalOutputIndex() const override;
++ virtual uint64_t globalOutputIndex() const override;
++ virtual bool spent() const override;
++ virtual bool frozen() const override;
++ virtual uint64_t spentHeight() const override;
++ virtual uint64_t amount() const override;
++ virtual bool rct() const override;
++ virtual bool keyImageKnown() const override;
++ virtual size_t pkIndex() const override;
++ virtual uint32_t subaddrIndex() const override;
++ virtual uint32_t subaddrAccount() const override;
++ virtual std::string address() const override;
++ virtual std::string addressLabel() const override;
++ virtual std::string keyImage() const override;
++ virtual uint64_t unlockTime() const override;
++ virtual bool unlocked() const override;
++ virtual std::string pubKey() const override;
++ virtual bool coinbase() const override;
++ virtual std::string description() const override;
++
++private:
++ uint64_t m_blockHeight;
++ std::string m_hash;
++ size_t m_internalOutputIndex;
++ uint64_t m_globalOutputIndex;
++ bool m_spent;
++ bool m_frozen;
++ uint64_t m_spentHeight;
++ uint64_t m_amount;
++ bool m_rct;
++ bool m_keyImageKnown;
++ size_t m_pkIndex;
++ uint32_t m_subaddrIndex;
++ uint32_t m_subaddrAccount;
++ std::string m_address;
++ std::string m_addressLabel;
++ std::string m_keyImage;
++ uint64_t m_unlockTime;
++ bool m_unlocked;
++ std::string m_pubKey;
++ bool m_coinbase;
++ std::string m_description;
++
++ friend class CoinsImpl;
++
++};
++
++} // namespace
++
++namespace Bitmonero = Monero;
++
++#endif //FEATHER_COINS_INFO_H
+diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
+index 67ac90a..6bb3a21 100644
+--- a/src/wallet/api/wallet.cpp
++++ b/src/wallet/api/wallet.cpp
+@@ -35,6 +35,7 @@
+ #include "transaction_history.h"
+ #include "address_book.h"
+ #include "subaddress.h"
++#include "coins.h"
+ #include "subaddress_account.h"
+ #include "common_defines.h"
+ #include "common/util.h"
+@@ -473,6 +474,7 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds)
+ m_wallet->set_refresh_enabled(false);
+ m_addressBook.reset(new AddressBookImpl(this));
+ m_subaddress.reset(new SubaddressImpl(this));
++ m_coins.reset(new CoinsImpl(this));
+ m_subaddressAccount.reset(new SubaddressAccountImpl(this));
+
+
+@@ -2046,7 +2048,7 @@ PendingTransaction* WalletImpl::restoreMultisigTransaction(const string& signDat
+ // - unconfirmed_transfer_details;
+ // - confirmed_transfer_details)
+
+-PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<string> &dst_addr, const string &payment_id, optional<std::vector<uint64_t>> amount, uint32_t mixin_count, PendingTransaction::Priority priority, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices)
++PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<string> &dst_addr, const string &payment_id, optional<std::vector<uint64_t>> amount, uint32_t mixin_count, PendingTransaction::Priority priority, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::set<std::string> &preferred_inputs)
+
+ {
+ clearStatus();
+@@ -2084,6 +2086,7 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
+ }
+ }
+ bool error = false;
++ uint64_t amountSum = 0;
+ for (size_t i = 0; i < dst_addr.size() && !error; i++) {
+ if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), dst_addr[i])) {
+ // TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982
+@@ -2105,6 +2108,7 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
+ de.original = dst_addr[i];
+ de.addr = info.address;
+ de.amount = (*amount)[i];
++ amountSum += (*amount)[i];
+ de.is_subaddress = info.is_subaddress;
+ de.is_integrated = info.has_payment_id;
+ dsts.push_back(de);
+@@ -2115,6 +2119,51 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
+ }
+ }
+ }
++ // uint64_t maxAllowedSpend = m_wallet->unlocked_balance(subaddr_account, true);
++ // if (maxAllowedSpend < amountSum) {
++ // error = true;
++ // setStatusError(tr("Amount you are trying to spend is larger than unlocked amount"));
++ // break;
++ // }
++ std::vector<crypto::key_image> preferred_input_list;
++ if (!preferred_inputs.empty()) {
++ LOG_ERROR("empty");
++
++ for (const auto &public_key : preferred_inputs) {
++ crypto::key_image keyImage;
++ bool r = epee::string_tools::hex_to_pod(public_key, keyImage);
++ if (!r) {
++ error = true;
++ setStatusError(tr("failed to parse key image"));
++ break;
++ }
++ if (m_wallet->frozen(keyImage)) {
++ error = true;
++ setStatusError(tr("refusing to spend frozen coin"));
++ break;
++ }
++
++ preferred_input_list.push_back(keyImage);
++ }
++ } else {
++ LOG_ERROR("not empty");
++
++ boost::shared_lock<boost::shared_mutex> transfers_lock(m_wallet->m_transfers_mutex);
++ for (size_t i = 0; i < m_wallet->get_num_transfer_details(); ++i) {
++ const tools::wallet2::transfer_details &td = m_wallet->get_transfer_details(i);
++ LOG_ERROR("COIN: " << i << ": " << td.amount() << "; "<<td.m_spent << ";" << td.m_frozen << ";" << m_wallet->frozen(td));
++ if (td.m_spent) continue;
++ LOG_ERROR("is frozen");
++ if (!td.m_frozen) {
++ LOG_ERROR("isn't:");
++ LOG_ERROR("hash: " << td.m_key_image << "; " << td.amount());
++ preferred_input_list.push_back(td.m_key_image);
++ }
++ }
++ }
++ for (const auto &de : preferred_input_list) {
++ LOG_ERROR("preferred input: " << de);
++ }
+ if (error) {
+ break;
+ }
+@@ -2129,11 +2178,11 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
+ if (amount) {
+ transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count,
+ adjusted_priority,
+- extra, subaddr_account, subaddr_indices);
++ extra, subaddr_account, subaddr_indices, preferred_input_list);
+ } else {
+ transaction->m_pending_tx = m_wallet->create_transactions_all(0, info.address, info.is_subaddress, 1, fake_outs_count,
+ adjusted_priority,
+- extra, subaddr_account, subaddr_indices);
++ extra, subaddr_account, subaddr_indices, preferred_input_list);
+ }
+ pendingTxPostProcess(transaction);
+
+@@ -2214,10 +2263,10 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
+ }
+
+ PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const string &payment_id, optional<uint64_t> amount, uint32_t mixin_count,
+- PendingTransaction::Priority priority, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices)
++ PendingTransaction::Priority priority, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::set<std::string> &preferred_inputs)
+
+ {
+- return createTransactionMultDest(std::vector<string> {dst_addr}, payment_id, amount ? (std::vector<uint64_t> {*amount}) : (optional<std::vector<uint64_t>>()), mixin_count, priority, subaddr_account, subaddr_indices);
++ return createTransactionMultDest(std::vector<string> {dst_addr}, payment_id, amount ? (std::vector<uint64_t> {*amount}) : (optional<std::vector<uint64_t>>()), mixin_count, priority, subaddr_account, subaddr_indices, preferred_inputs);
+ }
+
+ PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
+@@ -2342,6 +2391,11 @@ AddressBook *WalletImpl::addressBook()
+ return m_addressBook.get();
+ }
+
++Coins *WalletImpl::coins()
++{
++ return m_coins.get();
++}
++
+ Subaddress *WalletImpl::subaddress()
+ {
+ return m_subaddress.get();
+diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
+index 32e1228..a82f270 100644
+--- a/src/wallet/api/wallet.h
++++ b/src/wallet/api/wallet.h
+@@ -46,6 +46,7 @@ class PendingTransactionImpl;
+ class UnsignedTransactionImpl;
+ class AddressBookImpl;
+ class SubaddressImpl;
++class CoinsImpl;
+ class SubaddressAccountImpl;
+ struct Wallet2CallbackImpl;
+
+@@ -167,12 +168,14 @@ public:
+ optional<std::vector<uint64_t>> amount, uint32_t mixin_count,
+ PendingTransaction::Priority priority = PendingTransaction::Priority_Low,
+ uint32_t subaddr_account = 0,
+- std::set<uint32_t> subaddr_indices = {}) override;
++ std::set<uint32_t> subaddr_indices = {},
++ const std::set<std::string> &preferred_inputs = {}) override;
+ PendingTransaction * createTransaction(const std::string &dst_addr, const std::string &payment_id,
+ optional<uint64_t> amount, uint32_t mixin_count,
+ PendingTransaction::Priority priority = PendingTransaction::Priority_Low,
+ uint32_t subaddr_account = 0,
+- std::set<uint32_t> subaddr_indices = {}) override;
++ std::set<uint32_t> subaddr_indices = {},
++ const std::set<std::string> &preferred_inputs = {}) override;
+ virtual PendingTransaction * createSweepUnmixableTransaction() override;
+ bool submitTransaction(const std::string &fileName) override;
+ bool submitTransactionUR(const std::string &input) override;
+@@ -201,6 +204,7 @@ public:
+ PendingTransaction::Priority priority) const override;
+ virtual TransactionHistory * history() override;
+ virtual AddressBook * addressBook() override;
++ virtual Coins * coins() override;
+ virtual Subaddress * subaddress() override;
+ virtual SubaddressAccount * subaddressAccount() override;
+ virtual void setListener(WalletListener * l) override;
+@@ -272,6 +276,7 @@ private:
+ friend class TransactionHistoryImpl;
+ friend struct Wallet2CallbackImpl;
+ friend class AddressBookImpl;
++ friend class CoinsImpl;
+ friend class SubaddressImpl;
+ friend class SubaddressAccountImpl;
+
+@@ -288,6 +293,7 @@ private:
+ std::unique_ptr<Wallet2CallbackImpl> m_wallet2Callback;
+ std::unique_ptr<AddressBookImpl> m_addressBook;
+ std::unique_ptr<SubaddressImpl> m_subaddress;
++ std::unique_ptr<CoinsImpl> m_coins;
+ std::unique_ptr<SubaddressAccountImpl> m_subaddressAccount;
+
+ // multi-threaded refresh stuff
+diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
+index be1c370..013b5bc 100644
+--- a/src/wallet/api/wallet2_api.h
++++ b/src/wallet/api/wallet2_api.h
+@@ -263,6 +263,51 @@ struct AddressBook
+ virtual int lookupPaymentID(const std::string &payment_id) const = 0;
+ };
+
++/**
++ * @brief The CoinsInfo - interface for displaying coins information
++ */
++struct CoinsInfo
++{
++ virtual ~CoinsInfo() = 0;
++
++ virtual uint64_t blockHeight() const = 0;
++ virtual std::string hash() const = 0;
++ virtual size_t internalOutputIndex() const = 0;
++ virtual uint64_t globalOutputIndex() const = 0;
++ virtual bool spent() const = 0;
++ virtual bool frozen() const = 0;
++ virtual uint64_t spentHeight() const = 0;
++ virtual uint64_t amount() const = 0;
++ virtual bool rct() const = 0;
++ virtual bool keyImageKnown() const = 0;
++ virtual size_t pkIndex() const = 0;
++ virtual uint32_t subaddrIndex() const = 0;
++ virtual uint32_t subaddrAccount() const = 0;
++ virtual std::string address() const = 0;
++ virtual std::string addressLabel() const = 0;
++ virtual std::string keyImage() const = 0;
++ virtual uint64_t unlockTime() const = 0;
++ virtual bool unlocked() const = 0;
++ virtual std::string pubKey() const = 0;
++ virtual bool coinbase() const = 0;
++ virtual std::string description() const = 0;
++};
++
++struct Coins
++{
++ virtual ~Coins() = 0;
++ virtual int count() const = 0;
++ virtual CoinsInfo * coin(int index) const = 0;
++ virtual std::vector<CoinsInfo*> getAll() const = 0;
++ virtual void refresh() = 0;
++ virtual void setFrozen(std::string public_key) = 0;
++ virtual void setFrozen(int index) = 0;
++ virtual void thaw(std::string public_key) = 0;
++ virtual void thaw(int index) = 0;
++ virtual bool isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) = 0;
++ virtual void setDescription(const std::string &public_key, const std::string &description) = 0;
++};
++
+ struct SubaddressRow {
+ public:
+ SubaddressRow(std::size_t _rowId, const std::string &_address, const std::string &_label):
+@@ -856,7 +901,8 @@ struct Wallet
+ optional<std::vector<uint64_t>> amount, uint32_t mixin_count,
+ PendingTransaction::Priority = PendingTransaction::Priority_Low,
+ uint32_t subaddr_account = 0,
+- std::set<uint32_t> subaddr_indices = {}) = 0;
++ std::set<uint32_t> subaddr_indices = {},
++ const std::set<std::string> &preferred_inputs = {}) = 0;
+
+ /*!
+ * \brief createTransaction creates transaction. if dst_addr is an integrated address, payment_id is ignored
+@@ -875,7 +921,8 @@ struct Wallet
+ optional<uint64_t> amount, uint32_t mixin_count,
+ PendingTransaction::Priority = PendingTransaction::Priority_Low,
+ uint32_t subaddr_account = 0,
+- std::set<uint32_t> subaddr_indices = {}) = 0;
++ std::set<uint32_t> subaddr_indices = {},
++ const std::set<std::string> &preferred_inputs = {}) = 0;
+
+ /*!
+ * \brief createSweepUnmixableTransaction creates transaction with unmixable outputs.
+@@ -994,6 +1041,7 @@ struct Wallet
+
+ virtual TransactionHistory * history() = 0;
+ virtual AddressBook * addressBook() = 0;
++ virtual Coins * coins() = 0;
+ virtual Subaddress * subaddress() = 0;
+ virtual SubaddressAccount * subaddressAccount() = 0;
+ virtual void setListener(WalletListener *) = 0;
+diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
+index fa346a9..d060bf9 100644
+--- a/src/wallet/wallet2.cpp
++++ b/src/wallet/wallet2.cpp
+@@ -2094,12 +2094,21 @@ bool wallet2::frozen(const multisig_tx_set& txs) const
+
+ return false;
+ }
++void wallet2::freeze(const crypto::public_key &pk)
++{
++ freeze(get_transfer_details(pk));
++}
+ //----------------------------------------------------------------------------------------------------
+ void wallet2::freeze(const crypto::key_image &ki)
+ {
+ freeze(get_transfer_details(ki));
+ }
+ //----------------------------------------------------------------------------------------------------
++void wallet2::thaw(const crypto::public_key &pk)
++{
++ thaw(get_transfer_details(pk));
++}
++//----------------------------------------------------------------------------------------------------
+ void wallet2::thaw(const crypto::key_image &ki)
+ {
+ thaw(get_transfer_details(ki));
+@@ -2110,6 +2119,18 @@ bool wallet2::frozen(const crypto::key_image &ki) const
+ return frozen(get_transfer_details(ki));
+ }
+ //----------------------------------------------------------------------------------------------------
++size_t wallet2::get_transfer_details(const crypto::public_key &pk) const
++{
++ for (size_t idx = 0; idx < m_transfers.size(); ++idx)
++ {
++ const transfer_details &td = m_transfers[idx];
++ if (td.get_public_key() == pk) {
++ return idx;
++ }
++ }
++ CHECK_AND_ASSERT_THROW_MES(false, "Public key not found");
++}
++//----------------------------------------------------------------------------------------------------
+ size_t wallet2::get_transfer_details(const crypto::key_image &ki) const
+ {
+ for (size_t idx = 0; idx < m_transfers.size(); ++idx)
+@@ -2521,6 +2542,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)
+ {
++ boost::unique_lock<boost::shared_mutex> lock(m_transfers_mutex);
+ m_transfers.push_back(transfer_details{});
+ transfer_details& td = m_transfers.back();
+ td.m_block_height = height;
+@@ -2624,6 +2646,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+ uint64_t extra_amount = amount - burnt;
+ if (!pool)
+ {
++ boost::unique_lock<boost::shared_mutex> lock(m_transfers_mutex);
+ transfer_details &td = m_transfers[kit->second];
+ td.m_block_height = height;
+ td.m_internal_output_index = o;
+@@ -10500,7 +10523,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
+ LOG_PRINT_L2("transfer_selected_rct done");
+ }
+
+-std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices)
++std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list)
+ {
+ std::vector<size_t> picks;
+ float current_output_relatdness = 1.0f;
+@@ -10511,6 +10534,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];
++ if (!is_preferred_input(preferred_input_list, td.m_key_image)) {
++ continue;
++ }
+ 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)
+@@ -10531,6 +10557,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];
++ if (!is_preferred_input(preferred_input_list, td.m_key_image)) {
++ continue;
++ }
+ 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)
+@@ -10542,6 +10571,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];
++ if (!is_preferred_input(preferred_input_list, td2.m_key_image)) {
++ continue;
++ }
+ 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) << "]");
+@@ -11114,7 +11146,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.
+-std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const unique_index_container& subtract_fee_from_outputs)
++std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list, const unique_index_container& subtract_fee_from_outputs)
+ {
+ //ensure device is let in NONE mode in any case
+ hw::device &hwdev = m_account.get_device();
+@@ -11322,6 +11354,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];
++ if (!is_preferred_input(preferred_input_list, td.m_key_image)) {
++ continue;
++ }
+ 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));
+@@ -11413,7 +11448,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);
+- preferred_inputs = pick_preferred_rct_inputs(total_needed_money, subaddr_account, subaddr_indices);
++ preferred_inputs = pick_preferred_rct_inputs(total_needed_money, subaddr_account, subaddr_indices, preferred_input_list);
+ if (!preferred_inputs.empty())
+ {
+ string s;
+@@ -11892,7 +11927,7 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, c
+ return true;
+ }
+
+-std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices)
++std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list)
+ {
+ std::vector<size_t> unused_transfers_indices;
+ std::vector<size_t> unused_dust_indices;
+@@ -11921,6 +11956,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];
++ if (!is_preferred_input(preferred_input_list, td.m_key_image)) {
++ continue;
++ }
+ if (m_ignore_fractional_outputs && td.amount() < fractional_threshold)
+ {
+ 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 91cf2a3..bc16d52 100644
+--- a/src/wallet/wallet2.h
++++ b/src/wallet/wallet2.h
+@@ -1209,8 +1209,8 @@ private:
+ bool parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsigned_tx_set &exported_txs) const;
+ bool load_tx(const std::string &signed_filename, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set&)> accept_func = NULL);
+ bool parse_tx_from_str(const std::string &signed_tx_st, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set &)> accept_func);
+- std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const unique_index_container& subtract_fee_from_outputs = {}); // pass subaddr_indices by value on purpose
+- std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices);
++ std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list = {}, const unique_index_container& subtract_fee_from_outputs = {}); // pass subaddr_indices by value on purpose
++ std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list = {});
+ 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, 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, 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;
+@@ -1562,6 +1562,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;
++ size_t get_transfer_details(const crypto::public_key &pk) const;
+
+ uint8_t get_current_hard_fork();
+ void get_hard_fork_info(uint8_t version, uint64_t &earliest_height);
+@@ -1793,7 +1794,9 @@ private:
+ void freeze(size_t idx);
+ void thaw(size_t idx);
+ bool frozen(size_t idx) const;
++ void freeze(const crypto::public_key &pk);
+ void freeze(const crypto::key_image &ki);
++ void thaw(const crypto::public_key &pk);
+ void thaw(const crypto::key_image &ki);
+ bool frozen(const crypto::key_image &ki) const;
+ bool frozen(const transfer_details &td) const;
+@@ -1834,6 +1837,8 @@ private:
+
+ static std::string get_default_daemon_address() { CRITICAL_REGION_LOCAL(default_daemon_address_lock); return default_daemon_address; }
+
++ boost::shared_mutex m_transfers_mutex;
++
+ private:
+ /*!
+ * \brief Stores wallet information to wallet file.
+@@ -1905,7 +1910,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;
+- std::vector<size_t> pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices);
++ std::vector<size_t> pick_preferred_rct_inputs(uint64_t needed_money, uint32_t subaddr_account, const std::set<uint32_t> &subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list);
+ 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.39.5 (Apple Git-154)
+
diff --git a/patches/monero/0010-Add-hex-encoding-and-tx-key-getter-for-PendingTransc.patch b/patches/monero/0010-Add-hex-encoding-and-tx-key-getter-for-PendingTransc.patch
index e317627..6917daa 100644
--- a/patches/monero/0010-Add-hex-encoding-and-tx-key-getter-for-PendingTransc.patch
+++ b/patches/monero/0010-Add-hex-encoding-and-tx-key-getter-for-PendingTransc.patch
@@ -1,7 +1,7 @@
-From 3cc8b1f822f642b574fe38ff27627b362002eab7 Mon Sep 17 00:00:00 2001
+From 42aca87b69ecdc9fb24d14dd947f8bbffc7f3500 Mon Sep 17 00:00:00 2001
From: M <m@cakewallet.com>
Date: Fri, 21 Apr 2023 15:43:47 -0400
-Subject: [PATCH 10/16] Add hex encoding and tx key getter for
+Subject: [PATCH 10/14] Add hex encoding and tx key getter for
PendingTransction in wallet api.
---
@@ -11,10 +11,10 @@ Subject: [PATCH 10/16] Add hex encoding and tx key getter for
3 files changed, 20 insertions(+)
diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp
-index 70a702796..be20b478c 100644
+index 9c3c26e..1f714d2 100644
--- a/src/wallet/api/pending_transaction.cpp
+++ b/src/wallet/api/pending_transaction.cpp
-@@ -78,6 +78,22 @@ std::vector<std::string> PendingTransactionImpl::txid() const
+@@ -80,6 +80,22 @@ std::vector<std::string> PendingTransactionImpl::txid() const
return txid;
}
@@ -38,10 +38,10 @@ index 70a702796..be20b478c 100644
{
diff --git a/src/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h
-index 0a9779c07..2fbaa83d9 100644
+index 403bfe2..0cc6c58 100644
--- a/src/wallet/api/pending_transaction.h
+++ b/src/wallet/api/pending_transaction.h
-@@ -58,6 +58,8 @@ public:
+@@ -59,6 +59,8 @@ public:
std::string multisigSignData() override;
void signMultisigTx() override;
std::vector<std::string> signersKeys() const override;
@@ -51,10 +51,10 @@ index 0a9779c07..2fbaa83d9 100644
private:
friend class WalletImpl;
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
-index a585c8212..1c3a11c39 100644
+index 013b5bc..f421fdc 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
-@@ -126,6 +126,8 @@ struct PendingTransaction
+@@ -127,6 +127,8 @@ struct PendingTransaction
* @return vector of base58-encoded signers' public keys
*/
virtual std::vector<std::string> signersKeys() const = 0;
@@ -64,5 +64,5 @@ index a585c8212..1c3a11c39 100644
/**
--
-2.39.2
+2.39.5 (Apple Git-154)
diff --git a/patches/monero/0011-Add-recoverDeterministicWalletFromSpendKey.patch b/patches/monero/0011-Add-recoverDeterministicWalletFromSpendKey.patch
new file mode 100644
index 0000000..12d82ff
--- /dev/null
+++ b/patches/monero/0011-Add-recoverDeterministicWalletFromSpendKey.patch
@@ -0,0 +1,153 @@
+From ccddf3be96fd08d1eccbb58a7e8f8c98d07b07f2 Mon Sep 17 00:00:00 2001
+From: Konstantin Ullrich <konstantinullrich12@gmail.com>
+Date: Wed, 11 Oct 2023 16:47:59 +0200
+Subject: [PATCH 11/14] Add recoverDeterministicWalletFromSpendKey
+
+This function is used by Cake Wallet to enable polyseed (dart implementation)
+support.
+
+Sourced from the following commit:
+https://github.com/cake-tech/monero/commit/cb6fb5ab218878702ed151c0e3d5d68eb2732788
+
+Co-authored-by: Godwin Asuquo <godilite@gmail.com>
+---
+ src/wallet/api/wallet.cpp | 29 +++++++++++++++++++++++++++++
+ src/wallet/api/wallet.h | 4 ++++
+ src/wallet/api/wallet2_api.h | 19 +++++++++++++++++++
+ src/wallet/api/wallet_manager.cpp | 16 ++++++++++++++++
+ src/wallet/api/wallet_manager.h | 7 +++++++
+ 5 files changed, 75 insertions(+)
+
+diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
+index 6bb3a21..5734aff 100644
+--- a/src/wallet/api/wallet.cpp
++++ b/src/wallet/api/wallet.cpp
+@@ -824,6 +824,35 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c
+ return status() == Status_Ok;
+ }
+
++bool WalletImpl::recoverDeterministicWalletFromSpendKey(const std::string &path, const std::string &password, const std::string &language, const std::string &spendkey_string)
++{
++ clearStatus();
++ m_errorString.clear();
++
++ m_recoveringFromSeed = true;
++ m_recoveringFromDevice = false;
++
++ // parse spend key
++ crypto::secret_key spendkey;
++ if (!spendkey_string.empty()) {
++ cryptonote::blobdata spendkey_data;
++ if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key))
++ {
++ setStatusError(tr("failed to parse secret spend key"));
++ return false;
++ }
++ spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
++ }
++
++ try {
++ m_wallet->generate(path, password, spendkey, true, false);
++ setSeedLanguage(language);
++ } catch (const std::exception &e) {
++ setStatusCritical(e.what());
++ }
++ return status() == Status_Ok;
++}
++
+ bool WalletImpl::close(bool store)
+ {
+
+diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
+index a82f270..9e1fbb4 100644
+--- a/src/wallet/api/wallet.h
++++ b/src/wallet/api/wallet.h
+@@ -77,6 +77,10 @@ public:
+ const std::string &address_string,
+ const std::string &viewkey_string,
+ const std::string &spendkey_string = "");
++ bool recoverDeterministicWalletFromSpendKey(const std::string &path,
++ const std::string &password,
++ const std::string &language,
++ const std::string &spendkey_string);
+ bool recoverFromDevice(const std::string &path,
+ const std::string &password,
+ const std::string &device_name);
+diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
+index f421fdc..c8d6bb1 100644
+--- a/src/wallet/api/wallet2_api.h
++++ b/src/wallet/api/wallet2_api.h
+@@ -1323,6 +1323,25 @@ struct WalletManager
+ return createWalletFromKeys(path, password, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString);
+ }
+
++ /*!
++ * \brief recover deterministic wallet from spend key.
++ * \param path Name of wallet file to be created
++ * \param password Password of wallet file
++ * \param language language
++ * \param nettype Network type
++ * \param restoreHeight restore from start height
++ * \param spendKeyString spend key
++ * \param kdf_rounds Number of rounds for key derivation function
++ * \return Wallet instance (Wallet::status() needs to be called to check if recovered successfully)
++ */
++ virtual Wallet * createDeterministicWalletFromSpendKey(const std::string &path,
++ const std::string &password,
++ const std::string &language,
++ NetworkType nettype,
++ uint64_t restoreHeight,
++ const std::string &spendKeyString,
++ uint64_t kdf_rounds = 1) = 0;
++
+ /*!
+ * \deprecated this method creates a wallet WITHOUT a passphrase, use createWalletFromKeys(..., password, ...) instead
+ * \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
+diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
+index da2056d..c200f52 100644
+--- a/src/wallet/api/wallet_manager.cpp
++++ b/src/wallet/api/wallet_manager.cpp
+@@ -127,6 +127,22 @@ Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
+ return wallet;
+ }
+
++Wallet *WalletManagerImpl::createDeterministicWalletFromSpendKey(const std::string &path,
++ const std::string &password,
++ const std::string &language,
++ NetworkType nettype,
++ uint64_t restoreHeight,
++ const std::string &spendkey_string,
++ uint64_t kdf_rounds)
++{
++ WalletImpl * wallet = new WalletImpl(nettype, kdf_rounds);
++ if(restoreHeight > 0){
++ wallet->setRefreshFromBlockHeight(restoreHeight);
++ }
++ wallet->recoverDeterministicWalletFromSpendKey(path, password, language, spendkey_string);
++ return wallet;
++}
++
+ Wallet *WalletManagerImpl::createWalletFromDevice(const std::string &path,
+ const std::string &password,
+ NetworkType nettype,
+diff --git a/src/wallet/api/wallet_manager.h b/src/wallet/api/wallet_manager.h
+index 28fcd36..be3ff81 100644
+--- a/src/wallet/api/wallet_manager.h
++++ b/src/wallet/api/wallet_manager.h
+@@ -67,6 +67,13 @@ public:
+ const std::string &addressString,
+ const std::string &viewKeyString,
+ const std::string &spendKeyString = "") override;
++ virtual Wallet * createDeterministicWalletFromSpendKey(const std::string &path,
++ const std::string &password,
++ const std::string &language,
++ NetworkType nettype,
++ uint64_t restoreHeight,
++ const std::string &spendkey_string,
++ uint64_t kdf_rounds) override;
+ virtual Wallet * createWalletFromDevice(const std::string &path,
+ const std::string &password,
+ NetworkType nettype,
+--
+2.39.5 (Apple Git-154)
+
diff --git a/patches/monero/0012-add-monero-submodule-support.patch b/patches/monero/0012-add-monero-submodule-support.patch
new file mode 100644
index 0000000..d993a14
--- /dev/null
+++ b/patches/monero/0012-add-monero-submodule-support.patch
@@ -0,0 +1,65 @@
+From d8ab8f6fffd6235e935400f0fe750c1ba29b85e7 Mon Sep 17 00:00:00 2001
+From: cyan <cyjan@mrcyjanek.net>
+Date: Thu, 7 Nov 2024 16:46:24 +0000
+Subject: [PATCH 12/14] add monero submodule support
+
+---
+ CMakeLists.txt | 6 +++---
+ cmake/CheckLinkerFlag.cmake | 2 +-
+ src/wallet/wallet_rpc_server.cpp | 2 +-
+ 3 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index e7fa90a..b995a68 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -223,9 +223,9 @@ function(forbid_undefined_symbols)
+ cmake_minimum_required(VERSION 3.1)
+ project(test)
+ option(EXPECT_SUCCESS "" ON)
+-file(WRITE "${CMAKE_SOURCE_DIR}/incorrect_source.cpp" "void undefined_symbol(); void symbol() { undefined_symbol(); }")
++file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/incorrect_source.cpp" "void undefined_symbol(); void symbol() { undefined_symbol(); }")
+ if (EXPECT_SUCCESS)
+- file(APPEND "${CMAKE_SOURCE_DIR}/incorrect_source.cpp" " void undefined_symbol() {}; ")
++ file(APPEND "${CMAKE_CURRENT_SOURCE_DIR}/incorrect_source.cpp" " void undefined_symbol() {}; ")
+ endif()
+ add_library(l0 SHARED incorrect_source.cpp)
+ add_library(l1 MODULE incorrect_source.cpp)
+@@ -390,7 +390,7 @@ else()
+ endif()
+
+ list(INSERT CMAKE_MODULE_PATH 0
+- "${CMAKE_SOURCE_DIR}/cmake")
++ "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
+ if (NOT DEFINED ENV{DEVELOPER_LOCAL_TOOLS})
+ message(STATUS "Could not find DEVELOPER_LOCAL_TOOLS in env (not required)")
+diff --git a/cmake/CheckLinkerFlag.cmake b/cmake/CheckLinkerFlag.cmake
+index 7ecf5f6..89fb9d1 100644
+--- a/cmake/CheckLinkerFlag.cmake
++++ b/cmake/CheckLinkerFlag.cmake
+@@ -6,7 +6,7 @@ macro(CHECK_LINKER_FLAG flag VARIABLE)
+ message(STATUS "Looking for ${flag} linker flag")
+ endif()
+
+- set(_cle_source ${CMAKE_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
++ set(_cle_source ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
+
+ set(saved_CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
+ set(CMAKE_C_FLAGS "${flag}")
+diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
+index d24b4c5..91f6925 100644
+--- a/src/wallet/wallet_rpc_server.cpp
++++ b/src/wallet/wallet_rpc_server.cpp
+@@ -1163,7 +1163,7 @@ namespace tools
+ {
+ uint64_t mixin = m_wallet->adjust_mixin(req.ring_size ? req.ring_size - 1 : 0);
+ uint32_t priority = m_wallet->adjust_priority(req.priority);
+- std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, priority, extra, req.account_index, req.subaddr_indices, req.subtract_fee_from_outputs);
++ std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, priority, extra, req.account_index, req.subaddr_indices, {}, req.subtract_fee_from_outputs);
+
+ if (ptx_vector.empty())
+ {
+--
+2.39.5 (Apple Git-154)
+
diff --git a/patches/monero/0013-android-ndk-version-bump.patch b/patches/monero/0013-android-ndk-version-bump.patch
deleted file mode 100644
index 2b741a0..0000000
--- a/patches/monero/0013-android-ndk-version-bump.patch
+++ /dev/null
@@ -1,120 +0,0 @@
-From 1b978a697e1bdb3144bc08f998d125ac593fa971 Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Thu, 23 May 2024 08:02:49 +0200
-Subject: [PATCH 13/16] android ndk version bump
-
----
- contrib/depends/hosts/android.mk | 16 +++++++++++++---
- contrib/depends/packages/android_ndk.mk | 20 ++++++++++++++------
- contrib/depends/packages/boost.mk | 1 +
- contrib/depends/toolchain.cmake.in | 11 ++++++-----
- 4 files changed, 34 insertions(+), 14 deletions(-)
-
-diff --git a/contrib/depends/hosts/android.mk b/contrib/depends/hosts/android.mk
-index d6f8b99dd..e1c99aef3 100644
---- a/contrib/depends/hosts/android.mk
-+++ b/contrib/depends/hosts/android.mk
-@@ -1,12 +1,22 @@
- ANDROID_API=21
--
-+host_toolchain=nonexistent
- ifeq ($(host_arch),arm)
--host_toolchain=arm-linux-androideabi-
-+host_toolchain=armv7a-linux-androideabi${ANDROID_API}-
-+endif
-+ifeq ($(host_arch),x86_64)
-+host_toolchain=x86_64-linux-android${ANDROID_API}-
-+endif
-+ifeq ($(host_arch),i686)
-+host_toolchain=i686-linux-android${ANDROID_API}-
-+endif
-+ifeq ($(host_arch),aarch64)
-+host_toolchain=aarch64-linux-android${ANDROID_API}-
- endif
-
- android_CC=$(host_toolchain)clang
- android_CXX=$(host_toolchain)clang++
--android_RANLIB=:
-+android_RANLIB=llvm-ranlib
-+android_AR=llvm-ar
-
- android_CFLAGS=-pipe
- android_CXXFLAGS=$(android_CFLAGS)
-diff --git a/contrib/depends/packages/android_ndk.mk b/contrib/depends/packages/android_ndk.mk
-index 5deff76c7..1ad250653 100644
---- a/contrib/depends/packages/android_ndk.mk
-+++ b/contrib/depends/packages/android_ndk.mk
-@@ -1,8 +1,10 @@
- package=android_ndk
--$(package)_version=17b
-+$(package)_version=26d
- $(package)_download_path=https://dl.google.com/android/repository/
--$(package)_file_name=android-ndk-r$($(package)_version)-linux-x86_64.zip
--$(package)_sha256_hash=5dfbbdc2d3ba859fed90d0e978af87c71a91a5be1f6e1c40ba697503d48ccecd
-+$(package)_file_name=android-ndk-r$($(package)_version)-linux.zip
-+$(package)_sha256_hash=eefeafe7ccf177de7cc57158da585e7af119bb7504a63604ad719e4b2a328b54
-+
-+$(package)_version_apiversion=21
-
- define $(package)_set_vars
- $(package)_config_opts_arm=--arch arm
-@@ -17,8 +19,14 @@ define $(package)_extract_cmds
- endef
-
- define $(package)_stage_cmds
-- android-ndk-r$($(package)_version)/build/tools/make_standalone_toolchain.py --api 21 \
-- --install-dir $(build_prefix) --stl=libc++ $($(package)_config_opts) &&\
-- mv $(build_prefix) $($(package)_staging_dir)/$(host_prefix)
-+ mkdir -p $(build_prefix) &&\
-+ echo $(build_prefix)/toolchain && \
-+ android-ndk-r$($(package)_version)/build/tools/make_standalone_toolchain.py --api $($(package)_version_apiversion) \
-+ --install-dir $(build_prefix)/toolchain --stl=libc++ $($(package)_config_opts) &&\
-+ mv $(build_prefix)/toolchain $($(package)_staging_dir)/$(host_prefix)/native && \
-+ cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ar $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)$($(package)_version_apiversion)-ar &&\
-+ cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ranlib $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)$($(package)_version_apiversion)-ranlib &&\
-+ cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ar $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)-ar &&\
-+ cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ranlib $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)-ranlib
- endef
-
-diff --git a/contrib/depends/packages/boost.mk b/contrib/depends/packages/boost.mk
-index fd06c5393..c17e863cc 100644
---- a/contrib/depends/packages/boost.mk
-+++ b/contrib/depends/packages/boost.mk
-@@ -25,6 +25,7 @@ $(package)_archiver_darwin=$($(package)_libtool)
- $(package)_config_libraries=chrono,filesystem,program_options,system,thread,test,date_time,regex,serialization,locale
- $(package)_cxxflags=-std=c++11
- $(package)_cxxflags_linux=-fPIC
-+$(package)_cxxflags_android=-fPIC
- $(package)_cxxflags_freebsd=-fPIC
- endef
-
-diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in
-index f26655d68..96a95ceb8 100644
---- a/contrib/depends/toolchain.cmake.in
-+++ b/contrib/depends/toolchain.cmake.in
-@@ -104,16 +104,17 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
- SET(CMAKE_ANDROID_ARCH_ABI "armeabi-v7a")
- SET(CMAKE_SYSTEM_PROCESSOR "armv7-a")
- SET(CMAKE_ANDROID_ARM_MODE ON)
-- SET(CMAKE_C_COMPILER_TARGET arm-linux-androideabi)
-- SET(CMAKE_CXX_COMPILER_TARGET arm-linux-androideabi)
-- SET(_CMAKE_TOOLCHAIN_PREFIX arm-linux-androideabi-)
-+ SET(CMAKE_C_COMPILER_TARGET arm-linux-androideabi21)
-+ SET(CMAKE_CXX_COMPILER_TARGET arm-linux-androideabi21)
-+ SET(_CMAKE_TOOLCHAIN_PREFIX arm-linux-androideabi21-)
- elseif(ARCHITECTURE STREQUAL "aarch64")
- SET(CMAKE_ANDROID_ARCH_ABI "arm64-v8a")
- SET(CMAKE_SYSTEM_PROCESSOR "aarch64")
- endif()
- SET(CMAKE_ANDROID_STANDALONE_TOOLCHAIN @prefix@/native)
-- SET(CMAKE_C_COMPILER "${_CMAKE_TOOLCHAIN_PREFIX}clang")
-- SET(CMAKE_CXX_COMPILER "${_CMAKE_TOOLCHAIN_PREFIX}clang++")
-+ SET(_ANDROID_STANDALONE_TOOLCHAIN_API 21)
-+ SET(CMAKE_C_COMPILER @CC@)
-+ SET(CMAKE_CXX_COMPILER @CXX@)
- else()
- SET(CMAKE_C_COMPILER @CC@)
- SET(CMAKE_CXX_COMPILER @CXX@)
---
-2.39.2
-
diff --git a/patches/monero/0013-fix-iOS-depends-build.patch b/patches/monero/0013-fix-iOS-depends-build.patch
new file mode 100644
index 0000000..97c23c6
--- /dev/null
+++ b/patches/monero/0013-fix-iOS-depends-build.patch
@@ -0,0 +1,104 @@
+From dcb483e5cb97c4e3c500355d8225bd49d3e0ae7f Mon Sep 17 00:00:00 2001
+From: Czarek Nakamoto <cyjan@mrcyjanek.net>
+Date: Thu, 21 Nov 2024 06:05:03 -0500
+Subject: [PATCH 13/14] fix iOS depends build
+
+---
+ CMakeLists.txt | 4 ----
+ src/checkpoints/CMakeLists.txt | 6 +++++-
+ src/cryptonote_basic/CMakeLists.txt | 6 +++++-
+ src/cryptonote_basic/miner.cpp | 8 ++++----
+ 4 files changed, 14 insertions(+), 10 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index b995a68..4e86328 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -39,10 +39,6 @@ include(CheckLibraryExists)
+ include(CheckFunctionExists)
+ include(FindPythonInterp)
+
+-if (IOS)
+- INCLUDE(CmakeLists_IOS.txt)
+-endif()
+-
+ cmake_minimum_required(VERSION 3.5)
+ message(STATUS "CMake version ${CMAKE_VERSION}")
+
+diff --git a/src/checkpoints/CMakeLists.txt b/src/checkpoints/CMakeLists.txt
+index 665441f..841df32 100644
+--- a/src/checkpoints/CMakeLists.txt
++++ b/src/checkpoints/CMakeLists.txt
+@@ -28,7 +28,11 @@
+
+ if(APPLE)
+ if(DEPENDS)
+- list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
++ if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
++ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework IOKit")
++ else()
++ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
++ endif()
+ else()
+ find_library(IOKIT_LIBRARY IOKit)
+ mark_as_advanced(IOKIT_LIBRARY)
+diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt
+index 414936a..81c8176 100644
+--- a/src/cryptonote_basic/CMakeLists.txt
++++ b/src/cryptonote_basic/CMakeLists.txt
+@@ -28,7 +28,11 @@
+
+ if(APPLE)
+ if(DEPENDS)
+- list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
++ if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
++ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework IOKit")
++ else()
++ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
++ endif()
+ else()
+ find_library(IOKIT_LIBRARY IOKit)
+ mark_as_advanced(IOKIT_LIBRARY)
+diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
+index 71b8f78..0f53f02 100644
+--- a/src/cryptonote_basic/miner.cpp
++++ b/src/cryptonote_basic/miner.cpp
+@@ -45,7 +45,7 @@
+ #include "boost/logic/tribool.hpp"
+ #include <boost/filesystem.hpp>
+
+-#ifdef __APPLE__
++#if defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
+ #include <sys/times.h>
+ #include <IOKit/IOKitLib.h>
+ #include <IOKit/ps/IOPSKeys.h>
+@@ -883,7 +883,7 @@ namespace cryptonote
+
+ return true;
+
+- #elif defined(__APPLE__)
++ #elif defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
+
+ mach_msg_type_number_t count;
+ kern_return_t status;
+@@ -949,7 +949,7 @@ namespace cryptonote
+ return true;
+ }
+
+- #elif (defined(__linux__) && defined(_SC_CLK_TCK)) || defined(__APPLE__) || defined(__FreeBSD__)
++ #elif (defined(__linux__) && defined(_SC_CLK_TCK)) || (defined(__APPLE__) && !defined(TARGET_OS_IPHONE)) || defined(__FreeBSD__)
+
+ struct tms tms;
+ if ( times(&tms) != (clock_t)-1 )
+@@ -978,7 +978,7 @@ namespace cryptonote
+ return boost::logic::tribool(power_status.ACLineStatus != 1);
+ }
+
+- #elif defined(__APPLE__)
++ #elif defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
+
+ #if TARGET_OS_MAC && (!defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7)
+ return boost::logic::tribool(IOPSGetTimeRemainingEstimate() != kIOPSTimeRemainingUnlimited);
+--
+2.39.5 (Apple Git-154)
+
diff --git a/patches/monero/0014-include-locale-only-when-targeting-WIN32.patch b/patches/monero/0014-include-locale-only-when-targeting-WIN32.patch
new file mode 100644
index 0000000..4cd1d0c
--- /dev/null
+++ b/patches/monero/0014-include-locale-only-when-targeting-WIN32.patch
@@ -0,0 +1,43 @@
+From dfe8fde34cd51f5d5ec95fb464737f6e447d41bb Mon Sep 17 00:00:00 2001
+From: Czarek Nakamoto <cyjan@mrcyjanek.net>
+Date: Mon, 18 Nov 2024 10:57:37 -0500
+Subject: [PATCH 14/14] include locale only when targeting WIN32
+
+---
+ CMakeLists.txt | 5 ++++-
+ src/wallet/api/wallet.cpp | 2 ++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 4e86328..809bce6 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -1079,7 +1079,10 @@ if(STATIC)
+ set(Boost_USE_STATIC_LIBS ON)
+ set(Boost_USE_STATIC_RUNTIME ON)
+ endif()
+-find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options locale)
++if(WIN32)
++ set(BOOST_LOCALE locale)
++endif()
++find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options ${BOOST_LOCALE})
+ add_definitions(-DBOOST_ASIO_ENABLE_SEQUENTIAL_STRAND_ALLOCATION)
+
+ set(CMAKE_FIND_LIBRARY_SUFFIXES ${OLD_LIB_SUFFIXES})
+diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
+index 5734aff..f4fb093 100644
+--- a/src/wallet/api/wallet.cpp
++++ b/src/wallet/api/wallet.cpp
+@@ -46,7 +46,9 @@
+ #include <sstream>
+ #include <unordered_map>
+
++#ifdef WIN32
+ #include <boost/locale.hpp>
++#endif
+ #include <boost/filesystem.hpp>
+ #include "bc-ur/src/bc-ur.hpp"
+ #if defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI)
+--
+2.39.5 (Apple Git-154)
+
diff --git a/patches/monero/0014-rename-arm-armv7a.patch b/patches/monero/0014-rename-arm-armv7a.patch
deleted file mode 100644
index 20e2822..0000000
--- a/patches/monero/0014-rename-arm-armv7a.patch
+++ /dev/null
@@ -1,94 +0,0 @@
-From 2dfa0442a096f61fe16a5bc569a4d0ab9ddb7de5 Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Wed, 12 Jun 2024 15:48:01 +0200
-Subject: [PATCH 14/16] rename arm -> armv7a
-
----
- contrib/depends/hosts/android.mk | 2 +-
- contrib/depends/packages/android_ndk.mk | 6 +++++-
- contrib/depends/packages/openssl.mk | 2 +-
- contrib/depends/toolchain.cmake.in | 8 ++++----
- 4 files changed, 11 insertions(+), 7 deletions(-)
-
-diff --git a/contrib/depends/hosts/android.mk b/contrib/depends/hosts/android.mk
-index e1c99aef3..827103c36 100644
---- a/contrib/depends/hosts/android.mk
-+++ b/contrib/depends/hosts/android.mk
-@@ -1,6 +1,6 @@
- ANDROID_API=21
- host_toolchain=nonexistent
--ifeq ($(host_arch),arm)
-+ifeq ($(host_arch),armv7a)
- host_toolchain=armv7a-linux-androideabi${ANDROID_API}-
- endif
- ifeq ($(host_arch),x86_64)
-diff --git a/contrib/depends/packages/android_ndk.mk b/contrib/depends/packages/android_ndk.mk
-index 1ad250653..2c2914ec2 100644
---- a/contrib/depends/packages/android_ndk.mk
-+++ b/contrib/depends/packages/android_ndk.mk
-@@ -7,7 +7,7 @@ $(package)_sha256_hash=eefeafe7ccf177de7cc57158da585e7af119bb7504a63604ad719e4b2
- $(package)_version_apiversion=21
-
- define $(package)_set_vars
--$(package)_config_opts_arm=--arch arm
-+$(package)_config_opts_armv7a=--arch arm
- $(package)_config_opts_aarch64=--arch arm64
- $(package)_config_opts_x86_64=--arch x86_64
- $(package)_config_opts_i686=--arch x86
-@@ -18,6 +18,8 @@ define $(package)_extract_cmds
- unzip -q $($(1)_source_dir)/$($(package)_file_name)
- endef
-
-+# arm-linux-androideabi-ar - openssl workaround
-+
- define $(package)_stage_cmds
- mkdir -p $(build_prefix) &&\
- echo $(build_prefix)/toolchain && \
-@@ -25,7 +27,9 @@ define $(package)_stage_cmds
- --install-dir $(build_prefix)/toolchain --stl=libc++ $($(package)_config_opts) &&\
- mv $(build_prefix)/toolchain $($(package)_staging_dir)/$(host_prefix)/native && \
- cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ar $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)$($(package)_version_apiversion)-ar &&\
-+ cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ar $($(package)_staging_dir)/$(host_prefix)/native/bin/arm-linux-androideabi-ar &&\
- cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ranlib $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)$($(package)_version_apiversion)-ranlib &&\
-+ cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ranlib $($(package)_staging_dir)/$(host_prefix)/native/bin/arm-linux-androideabi-ranlib &&\
- cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ar $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)-ar &&\
- cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ranlib $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)-ranlib
- endef
-diff --git a/contrib/depends/packages/openssl.mk b/contrib/depends/packages/openssl.mk
-index a157762c7..2430f6495 100644
---- a/contrib/depends/packages/openssl.mk
-+++ b/contrib/depends/packages/openssl.mk
-@@ -34,7 +34,7 @@ $(package)_config_opts_x86_64_linux=linux-x86_64
- $(package)_config_opts_i686_linux=linux-generic32
- $(package)_config_opts_arm_linux=linux-generic32
- $(package)_config_opts_aarch64_linux=linux-generic64
--$(package)_config_opts_arm_android=--static android-arm
-+$(package)_config_opts_armv7a_android=--static android-arm
- $(package)_config_opts_aarch64_android=--static android-arm64
- $(package)_config_opts_aarch64_darwin=darwin64-arm64-cc
- $(package)_config_opts_riscv64_linux=linux-generic64
-diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in
-index 96a95ceb8..48a6f947e 100644
---- a/contrib/depends/toolchain.cmake.in
-+++ b/contrib/depends/toolchain.cmake.in
-@@ -100,13 +100,13 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
- SET(LLVM_ENABLE_PIE OFF)
- elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
- SET(ANDROID TRUE)
-- if(ARCHITECTURE STREQUAL "arm")
-+ if(ARCHITECTURE STREQUAL "armv7a")
- SET(CMAKE_ANDROID_ARCH_ABI "armeabi-v7a")
- SET(CMAKE_SYSTEM_PROCESSOR "armv7-a")
- SET(CMAKE_ANDROID_ARM_MODE ON)
-- SET(CMAKE_C_COMPILER_TARGET arm-linux-androideabi21)
-- SET(CMAKE_CXX_COMPILER_TARGET arm-linux-androideabi21)
-- SET(_CMAKE_TOOLCHAIN_PREFIX arm-linux-androideabi21-)
-+ SET(CMAKE_C_COMPILER_TARGET armv7a-linux-androideabi21)
-+ SET(CMAKE_CXX_COMPILER_TARGET armv7a-linux-androideabi21)
-+ SET(_CMAKE_TOOLCHAIN_PREFIX armv7a-linux-androideabi21-)
- elseif(ARCHITECTURE STREQUAL "aarch64")
- SET(CMAKE_ANDROID_ARCH_ABI "arm64-v8a")
- SET(CMAKE_SYSTEM_PROCESSOR "aarch64")
---
-2.39.2
-
diff --git a/patches/monero/0017-added-deps.patch b/patches/monero/0017-added-deps.patch
deleted file mode 100644
index 4edacce..0000000
--- a/patches/monero/0017-added-deps.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 8f0b07a685b5971f4deb66bb8c53e6da4065370c Mon Sep 17 00:00:00 2001
-From: cyan <cyjan@mrcyjanek.net>
-Date: Thu, 25 Jul 2024 20:06:29 +0000
-Subject: [PATCH] added deps
-
----
- external/polyseed | 1 +
- external/utf8proc | 1 +
- 2 files changed, 2 insertions(+)
- create mode 160000 external/polyseed
- create mode 160000 external/utf8proc
-
-diff --git a/external/polyseed b/external/polyseed
-new file mode 160000
-index 000000000..dfb05d8ed
---- /dev/null
-+++ b/external/polyseed
-@@ -0,0 +1 @@
-+Subproject commit dfb05d8edb682b0e8f743b1b70c9131712ff4157
-diff --git a/external/utf8proc b/external/utf8proc
-new file mode 160000
-index 000000000..5568eff49
---- /dev/null
-+++ b/external/utf8proc
-@@ -0,0 +1 @@
-+Subproject commit 5568eff49a6bf417b6fdef2808df9db8d3d68a76
---
-2.39.2
-
diff --git a/patches/monero/0018-fix-coin-control-patch.patch b/patches/monero/0018-fix-coin-control-patch.patch
deleted file mode 100644
index 001a1c0..0000000
--- a/patches/monero/0018-fix-coin-control-patch.patch
+++ /dev/null
@@ -1,30 +0,0 @@
-From 3d99b4efb5a79d7c52d596c349de25d1ca34c264 Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Fri, 27 Sep 2024 12:20:49 +0200
-Subject: [PATCH] fix coin control patch
-
----
- src/wallet/api/wallet.cpp | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index 3ead385ec..ec7d60ec0 100644
---- a/src/wallet/api/wallet.cpp
-+++ b/src/wallet/api/wallet.cpp
-@@ -2174,11 +2174,11 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
- if (amount) {
- transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count,
- adjusted_priority,
-- extra, subaddr_account, subaddr_indices);
-+ extra, subaddr_account, subaddr_indices, preferred_input_list);
- } else {
- transaction->m_pending_tx = m_wallet->create_transactions_all(0, info.address, info.is_subaddress, 1, fake_outs_count,
- adjusted_priority,
-- extra, subaddr_account, subaddr_indices);
-+ extra, subaddr_account, subaddr_indices, preferred_input_list);
- }
- pendingTxPostProcess(transaction);
-
---
-2.39.5 (Apple Git-154)
-
diff --git a/patches/monero/0019-fix-for-coin-control-patch.patch b/patches/monero/0019-fix-for-coin-control-patch.patch
deleted file mode 100644
index b7ff7f9..0000000
--- a/patches/monero/0019-fix-for-coin-control-patch.patch
+++ /dev/null
@@ -1,97 +0,0 @@
-From 8f93306ed526e0e573b33fc7dd40abbba7e7a00a Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Tue, 15 Oct 2024 18:00:05 +0200
-Subject: [PATCH] fix for coin control patch
-
----
- src/wallet/api/coins.cpp | 1 +
- src/wallet/api/wallet.cpp | 36 +++++++++++++++++++++++++++++++++++-
- 2 files changed, 36 insertions(+), 1 deletion(-)
-
-diff --git a/src/wallet/api/coins.cpp b/src/wallet/api/coins.cpp
-index 2321c638d..ef12141cf 100644
---- a/src/wallet/api/coins.cpp
-+++ b/src/wallet/api/coins.cpp
-@@ -114,6 +114,7 @@ void CoinsImpl::setFrozen(int index)
- {
- try
- {
-+ LOG_ERROR("Freezing coin: " << index);
- m_wallet->m_wallet->freeze(index);
- refresh();
- }
-diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index ec7d60ec0..db127dae4 100644
---- a/src/wallet/api/wallet.cpp
-+++ b/src/wallet/api/wallet.cpp
-@@ -2116,6 +2116,7 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
- }
- }
- bool error = false;
-+ uint64_t amountSum = 0;
- for (size_t i = 0; i < dst_addr.size() && !error; i++) {
- if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), dst_addr[i])) {
- // TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982
-@@ -2137,6 +2138,7 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
- de.original = dst_addr[i];
- de.addr = info.address;
- de.amount = (*amount)[i];
-+ amountSum += (*amount)[i];
- de.is_subaddress = info.is_subaddress;
- de.is_integrated = info.has_payment_id;
- dsts.push_back(de);
-@@ -2147,18 +2149,50 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
- }
- }
- }
-+ // uint64_t maxAllowedSpend = m_wallet->unlocked_balance(subaddr_account, true);
-+ // if (maxAllowedSpend < amountSum) {
-+ // error = true;
-+ // setStatusError(tr("Amount you are trying to spend is larger than unlocked amount"));
-+ // break;
-+ // }
- std::vector<crypto::key_image> preferred_input_list;
- if (!preferred_inputs.empty()) {
-+ LOG_ERROR("empty");
-+
- for (const auto &public_key : preferred_inputs) {
- crypto::key_image keyImage;
- bool r = epee::string_tools::hex_to_pod(public_key, keyImage);
-- if (!r) {
-+ if (!r) {
- error = true;
- setStatusError(tr("failed to parse key image"));
- break;
- }
-+ if (m_wallet->frozen(keyImage)) {
-+ error = true;
-+ setStatusError(tr("refusing to spend frozen coin"));
-+ break;
-+ }
-+
- preferred_input_list.push_back(keyImage);
- }
-+ } else {
-+ LOG_ERROR("not empty");
-+
-+ boost::shared_lock<boost::shared_mutex> transfers_lock(m_wallet->m_transfers_mutex);
-+ for (size_t i = 0; i < m_wallet->get_num_transfer_details(); ++i) {
-+ const tools::wallet2::transfer_details &td = m_wallet->get_transfer_details(i);
-+ LOG_ERROR("COIN: " << i << ": " << td.amount() << "; "<<td.m_spent << ";" << td.m_frozen << ";" << m_wallet->frozen(td));
-+ if (td.m_spent) continue;
-+ LOG_ERROR("is frozen");
-+ if (!td.m_frozen) {
-+ LOG_ERROR("isn't:");
-+ LOG_ERROR("hash: " << td.m_key_image << "; " << td.amount());
-+ preferred_input_list.push_back(td.m_key_image);
-+ }
-+ }
-+ }
-+ for (const auto &de : preferred_input_list) {
-+ LOG_ERROR("preferred input: " << de);
- }
- if (error) {
- break;
---
-2.39.5 (Apple Git-154)
-
diff --git a/patches/monero/0020-catch-exception-in-queryWalletDevice.patch b/patches/monero/0020-catch-exception-in-queryWalletDevice.patch
deleted file mode 100644
index 1fb2471..0000000
--- a/patches/monero/0020-catch-exception-in-queryWalletDevice.patch
+++ /dev/null
@@ -1,35 +0,0 @@
-From d0774a747e7520f6dae3cf90ecbb682395da8c9c Mon Sep 17 00:00:00 2001
-From: cyan <cyjan@mrcyjanek.net>
-Date: Wed, 27 Nov 2024 23:28:32 +0000
-Subject: [PATCH] catch exception in queryWalletDevice
-
----
- src/wallet/api/wallet_manager.cpp | 12 ++++++++----
- 1 file changed, 8 insertions(+), 4 deletions(-)
-
-diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
-index f88bd9e64..c200f52ae 100644
---- a/src/wallet/api/wallet_manager.cpp
-+++ b/src/wallet/api/wallet_manager.cpp
-@@ -213,10 +213,14 @@ bool WalletManagerImpl::verifyWalletPassword(const std::string &keys_file_name,
-
- bool WalletManagerImpl::queryWalletDevice(Wallet::Device& device_type, const std::string &keys_file_name, const std::string &password, uint64_t kdf_rounds) const
- {
-- hw::device::device_type type;
-- bool r = tools::wallet2::query_device(type, keys_file_name, password, kdf_rounds);
-- device_type = static_cast<Wallet::Device>(type);
-- return r;
-+ try {
-+ hw::device::device_type type;
-+ bool r = tools::wallet2::query_device(type, keys_file_name, password, kdf_rounds);
-+ device_type = static_cast<Wallet::Device>(type);
-+ return r;
-+ } catch (...) {
-+ return false;
-+ }
- }
-
- std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)
---
-2.43.0
-
diff --git a/patches/monero/README.md b/patches/monero/README.md
deleted file mode 100644
index b840515..0000000
--- a/patches/monero/README.md
+++ /dev/null
@@ -1,43 +0,0 @@
-
-> 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
-
-
-# 0001-polyseed
-
-Polyseed support for wallets [planned in long distant future as a part of walet3 - not getting upstream, no PR available].
-
-Note, only English support is available due to issues with normalization libraries.
-
-> 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)
-
-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
-
-# 0004-coin-control
-
-Coin control patch, I was able to trace it's orgins back to wownero/monerujo.
-
-# 0005-fix-build
-
-Fix cross compilation for linux
-
-# 0006-macos-build-fix
-
-Fixes cross compilation for MacOS targets
-
-# 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.
-
-# 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/0001-Fix-wallet_api-compilation-target-https-git.wownero..patch b/patches/wownero/0001-Fix-wallet_api-compilation-target-https-git.wownero..patch
deleted file mode 100644
index cf7a2cf..0000000
--- a/patches/wownero/0001-Fix-wallet_api-compilation-target-https-git.wownero..patch
+++ /dev/null
@@ -1,31 +0,0 @@
-From 1c32a5d6f62a550b9ee6635bca37f20a0471cc85 Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Tue, 26 Mar 2024 06:55:38 +0100
-Subject: [PATCH 01/14] Fix wallet_api compilation target
- https://git.wownero.com/wownero/wownero/issues/483
-
----
- src/wallet/api/wallet.cpp | 4 ++--
- 1 file changed, 2 insertions(+), 2 deletions(-)
-
-diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index 823f122c2..d81ddec93 100644
---- a/src/wallet/api/wallet.cpp
-+++ b/src/wallet/api/wallet.cpp
-@@ -1773,11 +1773,11 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
- if (amount) {
- transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */,
- adjusted_priority,
-- extra, subaddr_account, subaddr_indices, preferred_input_list);
-+ extra, subaddr_account, subaddr_indices);
- } else {
- transaction->m_pending_tx = m_wallet->create_transactions_all(0, info.address, info.is_subaddress, 1, fake_outs_count, 0 /* unlock_time */,
- adjusted_priority,
-- extra, subaddr_account, subaddr_indices, preferred_input_list);
-+ extra, subaddr_account, subaddr_indices);
- }
- pendingTxPostProcess(transaction);
-
---
-2.45.2
-
diff --git a/patches/wownero/0003-wallet-background-sync-with-just-the-view-key.patch b/patches/wownero/0001-wallet-background-sync-with-just-the-view-key.patch
index 10b6cd3..df672bd 100644
--- a/patches/wownero/0003-wallet-background-sync-with-just-the-view-key.patch
+++ b/patches/wownero/0001-wallet-background-sync-with-just-the-view-key.patch
@@ -1,7 +1,7 @@
-From bc5c17f6c9fcd6122de2c60625388e7370f9e522 Mon Sep 17 00:00:00 2001
+From 82bdb3dcf75f9e6bd8c5e31a125b8acc154a0623 Mon Sep 17 00:00:00 2001
From: j-berman <justinberman@protonmail.com>
Date: Thu, 13 Oct 2022 18:33:33 -0700
-Subject: [PATCH 03/14] wallet: background sync with just the view key
+Subject: [PATCH 01/15] 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
@@ -30,12 +30,12 @@ cache.
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.cpp | 204 +++-
src/simplewallet/simplewallet.h | 1 +
- src/wallet/api/wallet.cpp | 231 +++-
+ src/wallet/api/wallet.cpp | 213 +++-
src/wallet/api/wallet.h | 12 +
src/wallet/api/wallet2_api.h | 42 +
- src/wallet/wallet2.cpp | 1031 ++++++++++++++++--
+ src/wallet/wallet2.cpp | 1030 ++++++++++++++++--
src/wallet/wallet2.h | 156 ++-
src/wallet/wallet_errors.h | 39 +
src/wallet/wallet_rpc_server.cpp | 162 +++
@@ -47,14 +47,14 @@ cache.
tests/functional_tests/wallet.py | 43 +-
tests/unit_tests/wipeable_string.cpp | 12 +
utils/python-rpc/framework/wallet.py | 42 +
- 20 files changed, 2354 insertions(+), 133 deletions(-)
+ 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
+index 2ac455fda..4e87d4477 100644
--- a/src/cryptonote_basic/account.cpp
+++ b/src/cryptonote_basic/account.cpp
-@@ -158,6 +158,17 @@ DISABLE_VS_WARNINGS(4244 4345)
- m_keys.m_passphrase.wipe();
+@@ -152,6 +152,17 @@ DISABLE_VS_WARNINGS(4244 4345)
+ m_keys.m_multisig_keys.clear();
}
//-----------------------------------------------------------------
+ void account_base::set_spend_key(const crypto::secret_key& spend_secret_key)
@@ -72,10 +72,10 @@ index 4931c3740..2d556f285 100644
{
crypto::secret_key first = generate_keys(m_keys.m_account_address.m_spend_public_key, m_keys.m_spend_secret_key, recovery_key, recover);
diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h
-index 0099ebfe7..1f76febce 100644
+index 2ee9545d4..93d1d28f0 100644
--- a/src/cryptonote_basic/account.h
+++ b/src/cryptonote_basic/account.h
-@@ -101,6 +101,7 @@ namespace cryptonote
+@@ -95,6 +95,7 @@ namespace cryptonote
bool store(const std::string& file_path);
void forget_spend_key();
@@ -84,10 +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 5b36c70de..d9151e8d2 100644
+index 8c0d3ce20..8b5091a46 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
-@@ -255,6 +255,8 @@ namespace config
+@@ -253,6 +253,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;
@@ -97,7 +97,7 @@ index 5b36c70de..d9151e8d2 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..394201028 100644
+index 462c06f0e..8c5122097 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -155,6 +155,17 @@ typedef cryptonote::simple_wallet sw;
@@ -115,10 +115,10 @@ index b437092a4..394201028 100644
+ } \
+ } while (0)
+
- enum TransferType {
- Transfer,
- TransferLocked,
-@@ -332,7 +343,7 @@ namespace
+ static std::string get_human_readable_timespan(std::chrono::seconds seconds);
+ static std::string get_human_readable_timespan(uint64_t seconds);
+
+@@ -325,7 +336,7 @@ namespace
auto pwd_container = tools::password_container::prompt(verify, prompt);
if (!pwd_container)
{
@@ -127,7 +127,7 @@ index b437092a4..394201028 100644
}
return pwd_container;
}
-@@ -342,6 +353,11 @@ namespace
+@@ -335,6 +346,11 @@ namespace
return password_prompter(verify ? sw::tr("Enter a new password for the wallet") : sw::tr("Wallet password"), verify);
}
@@ -139,7 +139,7 @@ index b437092a4..394201028 100644
inline std::string interpret_rpc_response(bool ok, const std::string& status)
{
std::string err;
-@@ -459,6 +475,41 @@ namespace
+@@ -452,6 +468,41 @@ namespace
return "invalid";
}
@@ -181,7 +181,7 @@ index b437092a4..394201028 100644
std::string get_version_string(uint32_t version)
{
return boost::lexical_cast<std::string>(version >> 16) + "." + boost::lexical_cast<std::string>(version & 0xffff);
-@@ -812,6 +863,7 @@ bool simple_wallet::spendkey(const std::vector<std::string> &args/* = std::vecto
+@@ -805,6 +856,7 @@ bool simple_wallet::spendkey(const std::vector<std::string> &args/* = std::vecto
fail_msg_writer() << tr("wallet is watch-only and has no spend key");
return true;
}
@@ -189,7 +189,7 @@ index b437092a4..394201028 100644
// don't log
PAUSE_READLINE();
if (m_wallet->key_on_device()) {
-@@ -843,6 +895,7 @@ bool simple_wallet::print_seed(bool encrypted)
+@@ -836,6 +888,7 @@ bool simple_wallet::print_seed(bool encrypted)
fail_msg_writer() << tr("wallet is watch-only and has no seed");
return true;
}
@@ -197,7 +197,7 @@ index b437092a4..394201028 100644
multisig = m_wallet->multisig(&ready);
if (multisig)
-@@ -920,6 +973,7 @@ bool simple_wallet::seed_set_language(const std::vector<std::string> &args/* = s
+@@ -913,6 +966,7 @@ bool simple_wallet::seed_set_language(const std::vector<std::string> &args/* = s
fail_msg_writer() << tr("wallet is watch-only and has no seed");
return true;
}
@@ -205,7 +205,7 @@ index b437092a4..394201028 100644
epee::wipeable_string password;
{
-@@ -1066,6 +1120,7 @@ bool simple_wallet::prepare_multisig_main(const std::vector<std::string> &args,
+@@ -1059,6 +1113,7 @@ bool simple_wallet::prepare_multisig_main(const std::vector<std::string> &args,
fail_msg_writer() << tr("wallet is watch-only and cannot be made multisig");
return false;
}
@@ -213,7 +213,7 @@ index b437092a4..394201028 100644
if(m_wallet->get_num_transfer_details())
{
-@@ -2202,6 +2257,7 @@ bool simple_wallet::save_known_rings(const std::vector<std::string> &args)
+@@ -2195,6 +2250,7 @@ bool simple_wallet::save_known_rings(const std::vector<std::string> &args)
bool simple_wallet::freeze_thaw(const std::vector<std::string> &args, bool freeze)
{
@@ -221,7 +221,7 @@ index b437092a4..394201028 100644
if (args.empty())
{
fail_msg_writer() << boost::format(tr("usage: %s <key_image>|<pubkey>")) % (freeze ? "freeze" : "thaw");
-@@ -2241,6 +2297,7 @@ bool simple_wallet::thaw(const std::vector<std::string> &args)
+@@ -2234,6 +2290,7 @@ bool simple_wallet::thaw(const std::vector<std::string> &args)
bool simple_wallet::frozen(const std::vector<std::string> &args)
{
@@ -229,7 +229,7 @@ index b437092a4..394201028 100644
if (args.empty())
{
size_t ntd = m_wallet->get_num_transfer_details();
-@@ -3012,6 +3069,56 @@ bool simple_wallet::set_track_uses(const std::vector<std::string> &args/* = std:
+@@ -3005,6 +3062,57 @@ bool simple_wallet::set_track_uses(const std::vector<std::string> &args/* = std:
return true;
}
@@ -251,42 +251,43 @@ index b437092a4..394201028 100644
+ return true;
+ }
+
-+ const auto pwd_container = get_and_verify_password();
-+ if (pwd_container)
++ tools::wallet2::BackgroundSyncType background_sync_type;
++ if (!parse_background_sync_type(args[1], background_sync_type))
+ {
-+ tools::wallet2::BackgroundSyncType background_sync_type;
-+ if (!parse_background_sync_type(args[1], background_sync_type))
-+ {
-+ fail_msg_writer() << tr("invalid option");
-+ return true;
-+ }
++ fail_msg_writer() << tr("invalid option");
++ return true;
++ }
+
-+ try
-+ {
-+ boost::optional<epee::wipeable_string> background_cache_password = boost::none;
-+ if (background_sync_type == tools::wallet2::BackgroundSyncCustomPassword)
-+ {
-+ const auto background_pwd_container = background_sync_cache_password_prompter(true);
-+ if (!background_pwd_container)
-+ return true;
-+ background_cache_password = background_pwd_container->password();
-+ }
++ const auto pwd_container = get_and_verify_password();
++ if (!pwd_container)
++ return true;
+
-+ LOCK_IDLE_SCOPE();
-+ m_wallet->setup_background_sync(background_sync_type, pwd_container->password(), background_cache_password);
-+ }
-+ catch (const std::exception &e)
++ try
++ {
++ boost::optional<epee::wipeable_string> background_cache_password = boost::none;
++ if (background_sync_type == tools::wallet2::BackgroundSyncCustomPassword)
+ {
-+ fail_msg_writer() << tr("Error setting background sync type: ") << e.what();
++ const auto background_pwd_container = background_sync_cache_password_prompter(true);
++ if (!background_pwd_container)
++ return true;
++ background_cache_password = background_pwd_container->password();
+ }
++
++ LOCK_IDLE_SCOPE();
++ m_wallet->setup_background_sync(background_sync_type, pwd_container->password(), background_cache_password);
++ }
++ catch (const std::exception &e)
++ {
++ fail_msg_writer() << tr("Error setting background sync type: ") << e.what();
+ }
++
+ return true;
+}
+
bool simple_wallet::set_show_wallet_name_when_locked(const std::vector<std::string> &args/* = std::vector<std::string>()*/)
{
const auto pwd_container = get_and_verify_password();
-@@ -3257,6 +3364,7 @@ bool simple_wallet::apropos(const std::vector<std::string> &args)
+@@ -3237,6 +3345,7 @@ bool simple_wallet::apropos(const std::vector<std::string> &args)
bool simple_wallet::scan_tx(const std::vector<std::string> &args)
{
@@ -294,16 +295,16 @@ index b437092a4..394201028 100644
if (args.empty())
{
PRINT_USAGE(USAGE_SCAN_TX);
-@@ -3489,6 +3597,8 @@ simple_wallet::simple_wallet()
+@@ -3459,6 +3568,8 @@ simple_wallet::simple_wallet()
+ " Ignore outputs of amount above this threshold when spending. Value 0 is translated to the maximum value (18 million) which disables this filter.\n "
+ "ignore-outputs-below <amount>\n "
" 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 "
+ "track-uses <1|0>\n "
+ " Whether to keep track of owned outputs uses.\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)
+@@ -3879,6 +3990,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();
@@ -311,7 +312,7 @@ index b437092a4..394201028 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 +4039,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
+@@ -3897,6 +4009,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
}
else
{
@@ -319,15 +320,15 @@ index b437092a4..394201028 100644
#define CHECK_SIMPLE_VARIABLE(name, f, help) do \
if (args[0] == name) { \
-@@ -3981,6 +4093,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args)
+@@ -3950,6 +4063,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"));
+ CHECK_SIMPLE_VARIABLE("background-sync", setup_background_sync, tr("off (default); reuse-wallet-password (reuse the wallet password to encrypt the background cache); custom-background-password (use a custom background password to encrypt the background cache)"));
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 +5049,10 @@ std::string simple_wallet::get_mnemonic_language()
+ CHECK_SIMPLE_VARIABLE("setup-background-mining", set_setup_background_mining, tr("1/yes or 0/no"));
+@@ -4904,7 +5018,10 @@ std::string simple_wallet::get_mnemonic_language()
//----------------------------------------------------------------------------------------------------
boost::optional<tools::password_container> simple_wallet::get_and_verify_password() const
{
@@ -339,7 +340,7 @@ index b437092a4..394201028 100644
if (!pwd_container)
return boost::none;
-@@ -5240,6 +5356,8 @@ boost::optional<epee::wipeable_string> simple_wallet::open_wallet(const boost::p
+@@ -5208,6 +5325,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();
@@ -348,7 +349,7 @@ index b437092a4..394201028 100644
else
prefix = tr("Opened wallet");
message_writer(console_color_white, true) <<
-@@ -5447,6 +5565,10 @@ void simple_wallet::stop_background_mining()
+@@ -5415,6 +5534,10 @@ void simple_wallet::stop_background_mining()
//----------------------------------------------------------------------------------------------------
void simple_wallet::check_background_mining(const epee::wipeable_string &password)
{
@@ -359,7 +360,7 @@ index b437092a4..394201028 100644
tools::wallet2::BackgroundMiningSetupType setup = m_wallet->setup_background_mining();
if (setup == tools::wallet2::BackgroundMiningNo)
{
-@@ -6319,6 +6441,7 @@ bool simple_wallet::show_blockchain_height(const std::vector<std::string>& args)
+@@ -6287,6 +6410,7 @@ bool simple_wallet::show_blockchain_height(const std::vector<std::string>& args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::rescan_spent(const std::vector<std::string> &args)
{
@@ -367,7 +368,7 @@ index b437092a4..394201028 100644
if (!m_wallet->is_trusted_daemon())
{
fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon");
-@@ -6616,10 +6739,27 @@ void simple_wallet::check_for_inactivity_lock(bool user)
+@@ -6584,11 +6708,27 @@ void simple_wallet::check_for_inactivity_lock(bool user)
" B B " << std::endl <<
"" << std::endl;
}
@@ -390,13 +391,13 @@ index b437092a4..394201028 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 +6772,16 @@ void simple_wallet::check_for_inactivity_lock(bool user)
+ {
+@@ -6600,8 +6740,16 @@ void simple_wallet::check_for_inactivity_lock(bool user)
}
try
{
@@ -414,15 +415,15 @@ index b437092a4..394201028 100644
}
catch (...) { /* do nothing, just let the loop loop */ }
}
-@@ -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)
+@@ -6628,6 +6776,7 @@ bool simple_wallet::on_command(bool (simple_wallet::*cmd)(const std::vector<std:
+ bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool called_by_mms)
{
// "transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <amount> [<payment_id>]"
+ CHECK_IF_BACKGROUND_SYNCING("cannot transfer");
if (!try_connect_to_daemon())
return false;
-@@ -7133,6 +7282,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
+@@ -7056,6 +7205,7 @@ bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool ca
//----------------------------------------------------------------------------------------------------
bool simple_wallet::transfer(const std::vector<std::string> &args_)
{
@@ -430,23 +431,7 @@ index b437092a4..394201028 100644
if (args_.size() < 1)
{
PRINT_USAGE(USAGE_TRANSFER);
-@@ -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_)
- {
-+ CHECK_IF_BACKGROUND_SYNCING("cannot transfer");
- if (args_.size() < 1)
- {
- PRINT_USAGE(USAGE_LOCKED_TRANSFER);
-@@ -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_)
- {
-+ CHECK_IF_BACKGROUND_SYNCING("cannot sweep");
- if (args_.size() < 1)
- {
- PRINT_USAGE(USAGE_LOCKED_SWEEP_ALL);
-@@ -7167,6 +7319,7 @@ bool simple_wallet::locked_sweep_all(const std::vector<std::string> &args_)
+@@ -7068,6 +7218,7 @@ bool simple_wallet::transfer(const std::vector<std::string> &args_)
bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
{
@@ -454,15 +439,15 @@ index b437092a4..394201028 100644
if (!try_connect_to_daemon())
return true;
-@@ -7274,6 +7427,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
+@@ -7175,6 +7326,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_)
+ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, const std::vector<std::string> &args_)
{
+ CHECK_IF_BACKGROUND_SYNCING("cannot sweep");
auto print_usage = [this, account, below]()
{
if (below)
-@@ -7590,6 +7744,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co
+@@ -7456,6 +7608,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, const std::vect
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
{
@@ -470,12 +455,12 @@ index b437092a4..394201028 100644
if (!try_connect_to_daemon())
return true;
-@@ -7828,12 +7983,14 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
+@@ -7694,12 +7847,14 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sweep_all(const std::vector<std::string> &args_)
{
+ CHECK_IF_BACKGROUND_SYNCING("cannot sweep");
- sweep_main(m_current_subaddress_account, 0, false, args_);
+ sweep_main(m_current_subaddress_account, 0, args_);
return true;
}
//----------------------------------------------------------------------------------------------------
@@ -485,7 +470,7 @@ index b437092a4..394201028 100644
auto local_args = args_;
if (local_args.empty())
{
-@@ -7854,6 +8011,7 @@ bool simple_wallet::sweep_account(const std::vector<std::string> &args_)
+@@ -7720,6 +7875,7 @@ bool simple_wallet::sweep_account(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sweep_below(const std::vector<std::string> &args_)
{
@@ -493,7 +478,7 @@ index b437092a4..394201028 100644
uint64_t below = 0;
if (args_.size() < 1)
{
-@@ -7872,6 +8030,7 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_)
+@@ -7738,6 +7894,7 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::donate(const std::vector<std::string> &args_)
{
@@ -501,7 +486,7 @@ index b437092a4..394201028 100644
std::vector<std::string> local_args = args_;
if(local_args.empty() || local_args.size() > 5)
{
-@@ -7933,6 +8092,7 @@ bool simple_wallet::donate(const std::vector<std::string> &args_)
+@@ -7799,6 +7956,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)
{
@@ -509,15 +494,16 @@ index b437092a4..394201028 100644
// gather info to ask the user
uint64_t amount = 0, amount_to_dests = 0, change = 0;
size_t min_ring_size = ~0;
-@@ -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");
+@@ -7980,6 +8138,8 @@ bool simple_wallet::sign_transfer(const std::vector<std::string> &args_)
return true;
}
-+ CHECK_IF_BACKGROUND_SYNCING("cannot sign transfer");
++ CHECK_IF_BACKGROUND_SYNCING("cannot sign transfer");
++
bool export_raw = false;
std::string unsigned_filename = "unsigned_wownero_tx";
-@@ -8220,6 +8381,8 @@ std::string get_tx_key_stream(crypto::secret_key tx_key, std::vector<crypto::sec
+ if (args_.size() > 2 || (args_.size() == 2 && args_[0] != "export_raw"))
+@@ -8086,6 +8246,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_)
{
@@ -526,7 +512,7 @@ index b437092a4..394201028 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 +8423,8 @@ bool simple_wallet::get_tx_key(const std::vector<std::string> &args_)
+@@ -8126,6 +8288,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_)
{
@@ -535,7 +521,7 @@ index b437092a4..394201028 100644
std::vector<std::string> local_args = args_;
if(local_args.size() != 2 && local_args.size() != 3) {
-@@ -8336,6 +8501,8 @@ bool simple_wallet::set_tx_key(const std::vector<std::string> &args_)
+@@ -8202,6 +8366,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)
{
@@ -544,7 +530,7 @@ index b437092a4..394201028 100644
if (args.size() != 2 && args.size() != 3)
{
PRINT_USAGE(USAGE_GET_TX_PROOF);
-@@ -8542,6 +8709,7 @@ bool simple_wallet::check_tx_proof(const std::vector<std::string> &args)
+@@ -8408,6 +8574,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)
{
@@ -552,7 +538,7 @@ index b437092a4..394201028 100644
if (m_wallet->key_on_device())
{
fail_msg_writer() << tr("command not supported by HW wallet");
-@@ -8626,6 +8794,7 @@ bool simple_wallet::check_spend_proof(const std::vector<std::string> &args)
+@@ -8492,6 +8659,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)
{
@@ -560,7 +546,7 @@ index b437092a4..394201028 100644
if (m_wallet->key_on_device())
{
fail_msg_writer() << tr("command not supported by HW wallet");
-@@ -9312,6 +9481,8 @@ bool simple_wallet::unspent_outputs(const std::vector<std::string> &args_)
+@@ -9178,6 +9346,8 @@ bool simple_wallet::unspent_outputs(const std::vector<std::string> &args_)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::rescan_blockchain(const std::vector<std::string> &args_)
{
@@ -569,7 +555,7 @@ index b437092a4..394201028 100644
uint64_t start_height = 0;
ResetType reset_type = ResetSoft;
-@@ -9622,6 +9793,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
+@@ -9475,6 +9645,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
if (command == "new")
{
// create a new account and switch to it
@@ -577,7 +563,7 @@ index b437092a4..394201028 100644
std::string label = boost::join(local_args, " ");
if (label.empty())
label = tr("(Untitled account)");
-@@ -9652,6 +9824,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
+@@ -9505,6 +9676,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
@@ -585,7 +571,7 @@ index b437092a4..394201028 100644
uint32_t index_major;
if (!epee::string_tools::get_xtype_from_string(index_major, local_args[0]))
{
-@@ -9673,6 +9846,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
+@@ -9526,6 +9698,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
}
else if (command == "tag" && local_args.size() >= 2)
{
@@ -593,7 +579,7 @@ index b437092a4..394201028 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 +9871,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
+@@ -9550,6 +9723,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
}
else if (command == "untag" && local_args.size() >= 1)
{
@@ -601,7 +587,7 @@ index b437092a4..394201028 100644
std::set<uint32_t> account_indices;
for (size_t i = 0; i < local_args.size(); ++i)
{
-@@ -9720,6 +9895,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
+@@ -9573,6 +9747,7 @@ bool simple_wallet::account(const std::vector<std::string> &args/* = std::vector
}
else if (command == "tag_description" && local_args.size() >= 1)
{
@@ -609,7 +595,7 @@ index b437092a4..394201028 100644
const std::string tag = local_args[0];
std::string description;
if (local_args.size() > 1)
-@@ -9837,6 +10013,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
+@@ -9690,6 +9865,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
}
else if (local_args[0] == "new")
{
@@ -617,7 +603,7 @@ index b437092a4..394201028 100644
local_args.erase(local_args.begin());
std::string label;
if (local_args.size() > 0)
-@@ -9849,6 +10026,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
+@@ -9702,6 +9878,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
}
else if (local_args[0] == "mnew")
{
@@ -625,7 +611,7 @@ index b437092a4..394201028 100644
local_args.erase(local_args.begin());
if (local_args.size() != 1)
{
-@@ -9874,6 +10052,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
+@@ -9727,6 +9904,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
}
else if (local_args[0] == "one-off")
{
@@ -633,7 +619,7 @@ index b437092a4..394201028 100644
local_args.erase(local_args.begin());
std::string label;
if (local_args.size() != 2)
-@@ -9892,6 +10071,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
+@@ -9745,6 +9923,7 @@ bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::
}
else if (local_args.size() >= 2 && local_args[0] == "label")
{
@@ -641,7 +627,7 @@ index b437092a4..394201028 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 +10218,8 @@ bool simple_wallet::print_integrated_address(const std::vector<std::string> &arg
+@@ -9891,6 +10070,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>()*/)
{
@@ -650,7 +636,7 @@ index b437092a4..394201028 100644
if (args.size() == 0)
{
}
-@@ -10098,6 +10280,8 @@ bool simple_wallet::address_book(const std::vector<std::string> &args/* = std::v
+@@ -9951,6 +10132,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)
{
@@ -659,7 +645,7 @@ index b437092a4..394201028 100644
if (args.size() == 0)
{
PRINT_USAGE(USAGE_SET_TX_NOTE);
-@@ -10126,6 +10310,8 @@ bool simple_wallet::set_tx_note(const std::vector<std::string> &args)
+@@ -9979,6 +10162,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)
{
@@ -668,7 +654,7 @@ index b437092a4..394201028 100644
if (args.size() != 1)
{
PRINT_USAGE(USAGE_GET_TX_NOTE);
-@@ -10151,6 +10337,8 @@ bool simple_wallet::get_tx_note(const std::vector<std::string> &args)
+@@ -10004,6 +10189,8 @@ bool simple_wallet::get_tx_note(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::set_description(const std::vector<std::string> &args)
{
@@ -677,7 +663,7 @@ index b437092a4..394201028 100644
// 0 arguments allowed, for setting the description to empty string
std::string description = "";
-@@ -10167,6 +10355,8 @@ bool simple_wallet::set_description(const std::vector<std::string> &args)
+@@ -10020,6 +10207,8 @@ bool simple_wallet::set_description(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::get_description(const std::vector<std::string> &args)
{
@@ -686,7 +672,7 @@ index b437092a4..394201028 100644
if (args.size() != 0)
{
PRINT_USAGE(USAGE_GET_DESCRIPTION);
-@@ -10225,6 +10415,8 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args)
+@@ -10078,6 +10267,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();
@@ -695,7 +681,7 @@ index b437092a4..394201028 100644
else
type = tr("Normal");
message_writer() << tr("Type: ") << type;
-@@ -10236,6 +10428,7 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args)
+@@ -10089,6 +10280,7 @@ bool simple_wallet::wallet_info(const std::vector<std::string> &args)
//----------------------------------------------------------------------------------------------------
bool simple_wallet::sign(const std::vector<std::string> &args)
{
@@ -703,7 +689,7 @@ index b437092a4..394201028 100644
if (m_wallet->key_on_device())
{
fail_msg_writer() << tr("command not supported by HW wallet");
-@@ -10343,6 +10536,7 @@ bool simple_wallet::export_key_images(const std::vector<std::string> &args_)
+@@ -10196,6 +10388,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;
}
@@ -711,7 +697,7 @@ index b437092a4..394201028 100644
auto args = args_;
if (m_wallet->watch_only())
-@@ -10396,6 +10590,7 @@ bool simple_wallet::import_key_images(const std::vector<std::string> &args)
+@@ -10249,6 +10442,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;
}
@@ -719,7 +705,7 @@ index b437092a4..394201028 100644
if (!m_wallet->is_trusted_daemon())
{
fail_msg_writer() << tr("this command requires a trusted daemon. Enable with --trusted-daemon");
-@@ -10504,6 +10699,7 @@ bool simple_wallet::export_outputs(const std::vector<std::string> &args_)
+@@ -10357,6 +10551,7 @@ bool simple_wallet::export_outputs(const std::vector<std::string> &args_)
fail_msg_writer() << tr("command not supported by HW wallet");
return true;
}
@@ -727,7 +713,7 @@ index b437092a4..394201028 100644
auto args = args_;
bool all = false;
-@@ -10553,6 +10749,7 @@ bool simple_wallet::import_outputs(const std::vector<std::string> &args)
+@@ -10406,6 +10601,7 @@ bool simple_wallet::import_outputs(const std::vector<std::string> &args)
fail_msg_writer() << tr("command not supported by HW wallet");
return true;
}
@@ -736,7 +722,7 @@ index b437092a4..394201028 100644
{
PRINT_USAGE(USAGE_IMPORT_OUTPUTS);
diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h
-index 8e3477ba3..ae1aa312b 100644
+index d641dca1b..b98a40713 100644
--- a/src/simplewallet/simplewallet.h
+++ b/src/simplewallet/simplewallet.h
@@ -147,6 +147,7 @@ namespace cryptonote
@@ -745,13 +731,13 @@ index 8e3477ba3..ae1aa312b 100644
bool set_track_uses(const std::vector<std::string> &args = std::vector<std::string>());
+ bool setup_background_sync(const std::vector<std::string> &args = std::vector<std::string>());
bool set_show_wallet_name_when_locked(const std::vector<std::string> &args = std::vector<std::string>());
- 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>());
+ bool set_setup_background_mining(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..27a4dc6c8 100644
+index e81265ad3..e868fa039 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
-@@ -56,6 +56,40 @@ using namespace cryptonote;
+@@ -54,6 +54,40 @@ using namespace cryptonote;
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "WalletAPI"
@@ -792,7 +778,7 @@ index db9c2b5d9..27a4dc6c8 100644
namespace Monero {
namespace {
-@@ -836,6 +870,8 @@ bool WalletImpl::close(bool store)
+@@ -792,6 +826,8 @@ bool WalletImpl::close(bool store)
std::string WalletImpl::seed(const std::string& seed_offset) const
{
@@ -801,7 +787,7 @@ index db9c2b5d9..27a4dc6c8 100644
epee::wipeable_string seed;
if (m_wallet)
m_wallet->get_seed(seed, seed_offset);
-@@ -898,6 +934,8 @@ std::string WalletImpl::getSeedLanguage() const
+@@ -805,6 +841,8 @@ std::string WalletImpl::getSeedLanguage() const
void WalletImpl::setSeedLanguage(const std::string &arg)
{
@@ -810,7 +796,7 @@ index db9c2b5d9..27a4dc6c8 100644
m_wallet->set_seed_language(arg);
}
-@@ -921,6 +959,8 @@ void WalletImpl::statusWithErrorString(int& status, std::string& errorString) co
+@@ -828,6 +866,8 @@ void WalletImpl::statusWithErrorString(int& status, std::string& errorString) co
bool WalletImpl::setPassword(const std::string &password)
{
@@ -819,7 +805,7 @@ index db9c2b5d9..27a4dc6c8 100644
clearStatus();
try {
m_wallet->change_password(m_wallet->get_wallet_file(), m_password, password);
-@@ -1102,6 +1142,8 @@ bool WalletImpl::lightWalletImportWalletRequest(std::string &payment_id, uint64_
+@@ -988,6 +1028,8 @@ bool WalletImpl::lightWalletImportWalletRequest(std::string &payment_id, uint64_
void WalletImpl::setRefreshFromBlockHeight(uint64_t refresh_from_block_height)
{
@@ -828,7 +814,7 @@ index db9c2b5d9..27a4dc6c8 100644
m_wallet->set_refresh_from_block_height(refresh_from_block_height);
}
-@@ -1219,6 +1261,8 @@ void WalletImpl::refreshAsync()
+@@ -1105,6 +1147,8 @@ void WalletImpl::refreshAsync()
bool WalletImpl::rescanBlockchain()
{
@@ -837,7 +823,7 @@ index db9c2b5d9..27a4dc6c8 100644
clearStatus();
m_refreshShouldRescan = true;
doRefresh();
-@@ -1227,6 +1271,8 @@ bool WalletImpl::rescanBlockchain()
+@@ -1113,6 +1157,8 @@ bool WalletImpl::rescanBlockchain()
void WalletImpl::rescanBlockchainAsync()
{
@@ -846,7 +832,7 @@ index db9c2b5d9..27a4dc6c8 100644
m_refreshShouldRescan = true;
refreshAsync();
}
-@@ -1250,7 +1296,7 @@ int WalletImpl::autoRefreshInterval() const
+@@ -1136,7 +1182,7 @@ int WalletImpl::autoRefreshInterval() const
UnsignedTransaction *WalletImpl::loadUnsignedTx(const std::string &unsigned_filename) {
clearStatus();
UnsignedTransactionImpl * transaction = new UnsignedTransactionImpl(*this);
@@ -855,7 +841,7 @@ index db9c2b5d9..27a4dc6c8 100644
setStatusError(tr("Failed to load unsigned transactions"));
transaction->m_status = UnsignedTransaction::Status::Status_Error;
transaction->m_errorString = errorString();
-@@ -1312,6 +1358,8 @@ PendingTransaction *WalletImpl::loadSignedTx(const std::string &signed_filename)
+@@ -1156,6 +1202,8 @@ UnsignedTransaction *WalletImpl::loadUnsignedTx(const std::string &unsigned_file
bool WalletImpl::submitTransaction(const string &fileName) {
clearStatus();
@@ -864,7 +850,7 @@ index db9c2b5d9..27a4dc6c8 100644
std::unique_ptr<PendingTransactionImpl> transaction(new PendingTransactionImpl(*this));
bool r = m_wallet->load_tx(fileName, transaction->m_pending_tx);
-@@ -1335,6 +1383,8 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
+@@ -1179,6 +1227,8 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
setStatusError(tr("Wallet is view only"));
return false;
}
@@ -873,7 +859,7 @@ index db9c2b5d9..27a4dc6c8 100644
try
{
-@@ -1355,6 +1405,8 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
+@@ -1199,6 +1249,8 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
bool WalletImpl::importKeyImages(const string &filename)
{
@@ -882,7 +868,7 @@ index db9c2b5d9..27a4dc6c8 100644
if (!trustedDaemon()) {
setStatusError(tr("Key images can only be imported with a trusted daemon"));
return false;
-@@ -1378,6 +1430,8 @@ bool WalletImpl::importKeyImages(const string &filename)
+@@ -1222,6 +1274,8 @@ bool WalletImpl::importKeyImages(const string &filename)
bool WalletImpl::exportOutputs(const string &filename, bool all)
{
@@ -891,7 +877,7 @@ index db9c2b5d9..27a4dc6c8 100644
if (m_wallet->key_on_device())
{
setStatusError(string(tr("Not supported on HW wallets.")) + filename);
-@@ -1408,6 +1462,8 @@ bool WalletImpl::exportOutputs(const string &filename, bool all)
+@@ -1252,6 +1306,8 @@ bool WalletImpl::exportOutputs(const string &filename, bool all)
bool WalletImpl::importOutputs(const string &filename)
{
@@ -900,7 +886,7 @@ index db9c2b5d9..27a4dc6c8 100644
if (m_wallet->key_on_device())
{
setStatusError(string(tr("Not supported on HW wallets.")) + filename);
-@@ -1440,6 +1496,8 @@ bool WalletImpl::importOutputs(const string &filename)
+@@ -1284,6 +1340,8 @@ bool WalletImpl::importOutputs(const string &filename)
bool WalletImpl::scanTransactions(const std::vector<std::string> &txids)
{
@@ -909,7 +895,7 @@ index db9c2b5d9..27a4dc6c8 100644
if (txids.empty())
{
setStatusError(string(tr("Failed to scan transactions: no transaction ids provided.")));
-@@ -1563,8 +1621,86 @@ bool WalletImpl::importTransaction(const std::string &txid, std::vector<uint64_t
+@@ -1322,8 +1380,86 @@ bool WalletImpl::scanTransactions(const std::vector<std::string> &txids)
return true;
}
@@ -996,7 +982,7 @@ index db9c2b5d9..27a4dc6c8 100644
m_wallet->add_subaddress_account(label);
}
size_t WalletImpl::numSubaddressAccounts() const
-@@ -1577,10 +1713,14 @@ size_t WalletImpl::numSubaddresses(uint32_t accountIndex) const
+@@ -1336,10 +1472,14 @@ size_t WalletImpl::numSubaddresses(uint32_t accountIndex) const
}
void WalletImpl::addSubaddress(uint32_t accountIndex, const std::string& label)
{
@@ -1011,7 +997,7 @@ index db9c2b5d9..27a4dc6c8 100644
try
{
return m_wallet->get_subaddress_label({accountIndex, addressIndex});
-@@ -1594,6 +1734,8 @@ std::string WalletImpl::getSubaddressLabel(uint32_t accountIndex, uint32_t addre
+@@ -1353,6 +1493,8 @@ std::string WalletImpl::getSubaddressLabel(uint32_t accountIndex, uint32_t addre
}
void WalletImpl::setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex, const std::string &label)
{
@@ -1020,7 +1006,7 @@ index db9c2b5d9..27a4dc6c8 100644
try
{
return m_wallet->set_subaddress_label({accountIndex, addressIndex}, label);
-@@ -1607,12 +1749,16 @@ void WalletImpl::setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex
+@@ -1366,12 +1508,16 @@ void WalletImpl::setSubaddressLabel(uint32_t accountIndex, uint32_t addressIndex
MultisigState WalletImpl::multisig() const {
MultisigState state;
@@ -1037,7 +1023,7 @@ index db9c2b5d9..27a4dc6c8 100644
try {
clearStatus();
return m_wallet->get_multisig_first_kex_msg();
-@@ -1625,6 +1771,8 @@ string WalletImpl::getMultisigInfo() const {
+@@ -1384,6 +1530,8 @@ string WalletImpl::getMultisigInfo() const {
}
string WalletImpl::makeMultisig(const vector<string>& info, const uint32_t threshold) {
@@ -1046,7 +1032,7 @@ index db9c2b5d9..27a4dc6c8 100644
try {
clearStatus();
-@@ -1765,6 +1913,9 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
+@@ -1524,6 +1672,9 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
do {
@@ -1056,7 +1042,7 @@ index db9c2b5d9..27a4dc6c8 100644
std::vector<uint8_t> extra;
std::string extra_nonce;
vector<cryptonote::tx_destination_entry> dsts;
-@@ -2075,6 +2226,9 @@ PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
+@@ -1690,6 +1841,9 @@ PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
PendingTransactionImpl * transaction = new PendingTransactionImpl(*this);
do {
@@ -1066,7 +1052,7 @@ index db9c2b5d9..27a4dc6c8 100644
try {
transaction->m_pending_tx = m_wallet->create_unmixable_sweep_transactions();
pendingTxPostProcess(transaction);
-@@ -2213,11 +2367,15 @@ uint32_t WalletImpl::defaultMixin() const
+@@ -1823,11 +1977,15 @@ uint32_t WalletImpl::defaultMixin() const
void WalletImpl::setDefaultMixin(uint32_t arg)
{
@@ -1082,7 +1068,7 @@ index db9c2b5d9..27a4dc6c8 100644
m_wallet->set_attribute(key, val);
return true;
}
-@@ -2231,6 +2389,8 @@ std::string WalletImpl::getCacheAttribute(const std::string &key) const
+@@ -1841,6 +1999,8 @@ std::string WalletImpl::getCacheAttribute(const std::string &key) const
bool WalletImpl::setUserNote(const std::string &txid, const std::string &note)
{
@@ -1091,7 +1077,7 @@ index db9c2b5d9..27a4dc6c8 100644
cryptonote::blobdata txid_data;
if(!epee::string_tools::parse_hexstr_to_binbuff(txid, txid_data) || txid_data.size() != sizeof(crypto::hash))
return false;
-@@ -2242,6 +2402,8 @@ bool WalletImpl::setUserNote(const std::string &txid, const std::string &note)
+@@ -1852,6 +2012,8 @@ bool WalletImpl::setUserNote(const std::string &txid, const std::string &note)
std::string WalletImpl::getUserNote(const std::string &txid) const
{
@@ -1100,7 +1086,7 @@ index db9c2b5d9..27a4dc6c8 100644
cryptonote::blobdata txid_data;
if(!epee::string_tools::parse_hexstr_to_binbuff(txid, txid_data) || txid_data.size() != sizeof(crypto::hash))
return "";
-@@ -2252,6 +2414,9 @@ std::string WalletImpl::getUserNote(const std::string &txid) const
+@@ -1862,6 +2024,9 @@ std::string WalletImpl::getUserNote(const std::string &txid) const
std::string WalletImpl::getTxKey(const std::string &txid_str) const
{
@@ -1110,7 +1096,7 @@ index db9c2b5d9..27a4dc6c8 100644
crypto::hash txid;
if(!epee::string_tools::hex_to_pod(txid_str, txid))
{
-@@ -2336,6 +2501,9 @@ bool WalletImpl::checkTxKey(const std::string &txid_str, std::string tx_key_str,
+@@ -1946,6 +2111,9 @@ bool WalletImpl::checkTxKey(const std::string &txid_str, std::string tx_key_str,
std::string WalletImpl::getTxProof(const std::string &txid_str, const std::string &address_str, const std::string &message) const
{
@@ -1120,7 +1106,7 @@ index db9c2b5d9..27a4dc6c8 100644
crypto::hash txid;
if (!epee::string_tools::hex_to_pod(txid_str, txid))
{
-@@ -2392,6 +2560,9 @@ bool WalletImpl::checkTxProof(const std::string &txid_str, const std::string &ad
+@@ -2002,6 +2170,9 @@ bool WalletImpl::checkTxProof(const std::string &txid_str, const std::string &ad
}
std::string WalletImpl::getSpendProof(const std::string &txid_str, const std::string &message) const {
@@ -1130,7 +1116,7 @@ index db9c2b5d9..27a4dc6c8 100644
crypto::hash txid;
if(!epee::string_tools::hex_to_pod(txid_str, txid))
{
-@@ -2434,6 +2605,9 @@ bool WalletImpl::checkSpendProof(const std::string &txid_str, const std::string
+@@ -2044,6 +2215,9 @@ bool WalletImpl::checkSpendProof(const std::string &txid_str, const std::string
}
std::string WalletImpl::getReserveProof(bool all, uint32_t account_index, uint64_t amount, const std::string &message) const {
@@ -1140,7 +1126,7 @@ index db9c2b5d9..27a4dc6c8 100644
try
{
clearStatus();
-@@ -2480,6 +2654,9 @@ bool WalletImpl::checkReserveProof(const std::string &address, const std::string
+@@ -2090,6 +2264,9 @@ bool WalletImpl::checkReserveProof(const std::string &address, const std::string
std::string WalletImpl::signMessage(const std::string &message, const std::string &address)
{
@@ -1150,7 +1136,7 @@ index db9c2b5d9..27a4dc6c8 100644
if (address.empty()) {
return m_wallet->sign(message, tools::wallet2::sign_with_spend_key);
}
-@@ -2607,6 +2784,16 @@ bool WalletImpl::isDeterministic() const
+@@ -2217,6 +2394,16 @@ bool WalletImpl::isDeterministic() const
return m_wallet->is_deterministic();
}
@@ -1167,36 +1153,18 @@ index db9c2b5d9..27a4dc6c8 100644
void WalletImpl::clearStatus() const
{
boost::lock_guard<boost::mutex> l(m_statusMutex);
-@@ -2670,11 +2857,23 @@ 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;
-+
-+ // 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());
+@@ -2285,9 +2472,7 @@ void WalletImpl::doRefresh()
+ if(rescan)
+ m_wallet->rescan_blockchain(false);
+ m_wallet->refresh(trustedDaemon());
+- if (!m_synchronized) {
+- m_synchronized = true;
+- }
+ 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
-@@ -2784,6 +2983,24 @@ bool WalletImpl::doInit(const string &daemon_address, const std::string &proxy_a
+ // 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
+@@ -2391,6 +2576,24 @@ bool WalletImpl::doInit(const string &daemon_address, const std::string &proxy_a
return true;
}
@@ -1221,7 +1189,7 @@ index db9c2b5d9..27a4dc6c8 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 +3019,8 @@ std::string WalletImpl::getDefaultDataDir() const
+@@ -2409,6 +2612,8 @@ std::string WalletImpl::getDefaultDataDir() const
bool WalletImpl::rescanSpent()
{
clearStatus();
@@ -1231,12 +1199,12 @@ index db9c2b5d9..27a4dc6c8 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..fc6341861 100644
+index ec2d7e9b3..1f199a72c 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
-@@ -216,6 +216,13 @@ public:
- virtual std::string printAddressBook() override;
- virtual std::string printScannedPoolTxs() override;
+@@ -171,6 +171,13 @@ public:
+ bool importOutputs(const std::string &filename) override;
+ bool scanTransactions(const std::vector<std::string> &txids) 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;
@@ -1248,7 +1216,7 @@ index 28135c82a..fc6341861 100644
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:
+@@ -239,6 +246,7 @@ private:
bool isNewWallet() const;
void pendingTxPostProcess(PendingTransactionImpl * pending);
bool doInit(const std::string &daemon_address, const std::string &proxy_address, uint64_t upper_transaction_size_limit = 0, bool ssl = false);
@@ -1256,7 +1224,7 @@ index 28135c82a..fc6341861 100644
private:
friend class PendingTransactionImpl;
-@@ -302,6 +310,10 @@ private:
+@@ -253,6 +261,10 @@ private:
mutable boost::mutex m_statusMutex;
mutable int m_status;
mutable std::string m_errorString;
@@ -1268,10 +1236,10 @@ index 28135c82a..fc6341861 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..db5509227 100644
+index 71991df0d..e349df176 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
-@@ -544,6 +544,12 @@ struct Wallet
+@@ -445,6 +445,12 @@ struct Wallet
ConnectionStatus_WrongVersion
};
@@ -1284,9 +1252,9 @@ index a0ed60a39..db5509227 100644
virtual ~Wallet() = 0;
virtual std::string seed(const std::string& seed_offset = "") const = 0;
virtual std::string getSeedLanguage() const = 0;
-@@ -1095,6 +1101,42 @@ struct Wallet
-
- 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;
+@@ -936,6 +942,42 @@ struct Wallet
+ */
+ virtual bool scanTransactions(const std::vector<std::string> &txids) = 0;
+ /*!
+ * \brief setupBackgroundSync - setup background sync mode with just a view key
@@ -1326,12 +1294,12 @@ index a0ed60a39..db5509227 100644
+
virtual TransactionHistory * history() = 0;
virtual AddressBook * addressBook() = 0;
- virtual Coins * coins() = 0;
+ virtual Subaddress * subaddress() = 0;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
-index dfcc206a0..e013313b9 100644
+index 30b3502dc..8ce515c57 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
-@@ -158,6 +158,8 @@ static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1";
+@@ -157,6 +157,8 @@ static const std::string MULTISIG_SIGNATURE_MAGIC = "SigMultisigPkV1";
static const std::string ASCII_OUTPUT_MAGIC = "WowneroAsciiDataV1";
@@ -1340,7 +1308,7 @@ index dfcc206a0..e013313b9 100644
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)
+@@ -1009,14 +1011,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
*/
@@ -1357,7 +1325,7 @@ index dfcc206a0..e013313b9 100644
cn_fast_hash(cache_key_data.data(), HASH_SIZE+1, (crypto::hash&) cache_key);
return cache_key;
-@@ -1116,7 +1118,7 @@ wallet_keys_unlocker::wallet_keys_unlocker(wallet2 &w, const boost::optional<too
+@@ -1104,7 +1106,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;
@@ -1366,7 +1334,7 @@ index dfcc206a0..e013313b9 100644
{
locked = false;
return;
-@@ -1233,6 +1235,11 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
+@@ -1221,6 +1223,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),
@@ -1375,10 +1343,10 @@ index dfcc206a0..e013313b9 100644
+ 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_show_wallet_name_when_locked(false),
m_inactivity_lock_timeout(DEFAULT_INACTIVITY_LOCK_TIMEOUT),
-@@ -1897,6 +1904,9 @@ bool has_nonrequested_tx_at_height_or_above_requested(uint64_t height, const std
+ m_setup_background_mining(BackgroundMiningNo),
+@@ -1860,6 +1867,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)
{
@@ -1388,7 +1356,7 @@ index dfcc206a0..e013313b9 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 +2216,11 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons
+@@ -2169,11 +2179,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
@@ -1402,7 +1370,7 @@ index dfcc206a0..e013313b9 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 +2232,7 @@ void wallet2::scan_output(const cryptonote::transaction &tx, bool miner_tx, cons
+@@ -2185,7 +2195,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");
@@ -1411,7 +1379,7 @@ index dfcc206a0..e013313b9 100644
{
tx_scan_info.in_ephemeral.pub = output_public_key;
tx_scan_info.in_ephemeral.sec = crypto::null_skey;
-@@ -2479,6 +2489,22 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+@@ -2442,6 +2452,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()));
@@ -1434,16 +1402,16 @@ index dfcc206a0..e013313b9 100644
}
for(size_t o: outs)
-@@ -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;
+@@ -2467,7 +2493,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;
- td.m_key_image_known = !m_watch_only && !m_multisig;
+ td.m_key_image_known = !m_watch_only && !m_multisig && !m_background_syncing;
if (!td.m_key_image_known)
{
// we might have cold signed, and have a mapping to key images
-@@ -2696,10 +2722,25 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+@@ -2657,10 +2683,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);
@@ -1470,7 +1438,7 @@ index dfcc206a0..e013313b9 100644
{
PERF_TIMER(track_uses);
const uint64_t amount = in_to_key.amount;
-@@ -2713,7 +2754,27 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+@@ -2674,7 +2715,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");
@@ -1499,7 +1467,7 @@ index dfcc206a0..e013313b9 100644
}
}
}
-@@ -2723,7 +2784,24 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+@@ -2684,7 +2745,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)
@@ -1525,7 +1493,7 @@ index dfcc206a0..e013313b9 100644
}
}
}
-@@ -3096,8 +3174,8 @@ void wallet2::pull_blocks(bool first, bool try_incremental, uint64_t start_heigh
+@@ -3057,8 +3135,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;
@@ -1536,7 +1504,7 @@ index dfcc206a0..e013313b9 100644
req.pool_info_since = m_pool_info_query_time;
{
-@@ -3124,7 +3202,7 @@ void wallet2::pull_blocks(bool first, bool try_incremental, uint64_t start_heigh
+@@ -3085,7 +3163,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));
@@ -1545,7 +1513,7 @@ index dfcc206a0..e013313b9 100644
{
if (res.pool_info_extent != COMMAND_RPC_GET_BLOCKS_FAST::NONE)
{
-@@ -3636,6 +3714,9 @@ void wallet2::process_unconfirmed_transfer(bool incremental, const crypto::hash
+@@ -3597,6 +3675,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)
{
@@ -1555,7 +1523,7 @@ index dfcc206a0..e013313b9 100644
bool updated = false;
if (m_pool_info_query_time != 0 && try_incremental)
{
-@@ -4262,6 +4343,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
+@@ -4168,6 +4249,8 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
}
m_first_refresh_done = true;
@@ -1564,7 +1532,7 @@ index dfcc206a0..e013313b9 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 +4430,14 @@ wallet2::detached_blockchain_data wallet2::detach_blockchain(uint64_t height, st
+@@ -4253,6 +4336,14 @@ wallet2::detached_blockchain_data wallet2::detach_blockchain(uint64_t height, st
td.m_uses.pop_back();
}
@@ -1579,7 +1547,7 @@ index dfcc206a0..e013313b9 100644
if (output_tracker_cache)
output_tracker_cache->clear();
-@@ -4421,8 +4512,12 @@ void wallet2::handle_reorg(uint64_t height, std::map<std::pair<uint64_t, uint64_
+@@ -4327,8 +4418,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");
@@ -1592,7 +1560,7 @@ index dfcc206a0..e013313b9 100644
if (m_callback)
m_callback->on_reorg(height, dbd.detached_blockchain.size(), dbd.detached_tx_hashes.size());
}
-@@ -4432,6 +4527,7 @@ bool wallet2::deinit()
+@@ -4338,6 +4433,7 @@ bool wallet2::deinit()
if(m_is_initialized) {
m_is_initialized = false;
unlock_keys_file();
@@ -1600,7 +1568,7 @@ index dfcc206a0..e013313b9 100644
m_account.deinit();
}
return true;
-@@ -4458,6 +4554,7 @@ bool wallet2::clear()
+@@ -4364,6 +4460,7 @@ bool wallet2::clear()
m_device_last_key_image_sync = 0;
m_pool_info_query_time = 0;
m_skip_to_height = 0;
@@ -1608,7 +1576,7 @@ index dfcc206a0..e013313b9 100644
return true;
}
//----------------------------------------------------------------------------------------------------
-@@ -4476,13 +4573,30 @@ void wallet2::clear_soft(bool keep_key_images)
+@@ -4382,13 +4479,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;
@@ -1640,7 +1608,7 @@ index dfcc206a0..e013313b9 100644
/*!
* \brief Stores wallet information to wallet file.
* \param keys_file_name Name of wallet file
-@@ -4494,16 +4608,35 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
+@@ -4400,16 +4514,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");
@@ -1680,7 +1648,7 @@ index dfcc206a0..e013313b9 100644
if (e) {
boost::filesystem::remove(tmp_file_name);
-@@ -4515,26 +4648,27 @@ bool wallet2::store_keys(const std::string& keys_file_name, const epee::wipeable
+@@ -4421,26 +4554,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)
@@ -1716,7 +1684,7 @@ index dfcc206a0..e013313b9 100644
account.forget_spend_key();
account.encrypt_keys(key);
-@@ -4669,6 +4803,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
+@@ -4575,6 +4709,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());
@@ -1726,19 +1694,20 @@ index dfcc206a0..e013313b9 100644
value2.SetInt(m_show_wallet_name_when_locked ? 1 : 0);
json.AddMember("show_wallet_name_when_locked", value2, json.GetAllocator());
-@@ -4731,6 +4868,11 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
+@@ -4632,6 +4769,12 @@ 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());
- 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());
+ }
-
++
// Serialize the JSON object
rapidjson::StringBuffer buffer;
-@@ -4758,13 +4900,81 @@ void wallet2::setup_keys(const epee::wipeable_string &password)
+ rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
+@@ -4658,13 +4801,81 @@ void wallet2::setup_keys(const epee::wipeable_string &password)
m_account.decrypt_viewkey(key);
}
@@ -1821,7 +1790,7 @@ index dfcc206a0..e013313b9 100644
if (m_ask_password == AskPasswordToDecrypt && !m_unattended && !m_watch_only)
decrypt_keys(original_password);
setup_keys(new_password);
-@@ -4823,8 +5033,24 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+@@ -4723,8 +4934,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]);
@@ -1847,28 +1816,26 @@ index dfcc206a0..e013313b9 100644
// The contents should be JSON if the wallet follows the new format.
if (json.Parse(account_data.c_str()).HasParseError())
{
-@@ -4862,7 +5088,8 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+@@ -4762,6 +4989,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;
-- m_show_wallet_name_when_locked = true;
+ m_background_sync_type = BackgroundSyncOff;
-+ m_show_wallet_name_when_locked = false;
- m_show_detailed_prompt = true;
+ m_show_wallet_name_when_locked = false;
m_inactivity_lock_timeout = DEFAULT_INACTIVITY_LOCK_TIMEOUT;
m_setup_background_mining = BackgroundMiningNo;
-@@ -4881,6 +5108,7 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+@@ -4779,6 +5007,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_polyseed = false;
+ m_allow_mismatched_daemon_version = true;
+ m_custom_background_key = boost::none;
}
else if(json.IsObject())
{
-@@ -5121,6 +5349,39 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+@@ -5015,6 +5244,39 @@ 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;
- 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;
@@ -1905,7 +1872,7 @@ index dfcc206a0..e013313b9 100644
}
else
{
-@@ -5184,12 +5445,17 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+@@ -5078,12 +5340,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);
@@ -1925,7 +1892,7 @@ index dfcc206a0..e013313b9 100644
return true;
}
-@@ -5204,11 +5470,12 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+@@ -5098,11 +5365,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
*
*/
@@ -1940,7 +1907,7 @@ index dfcc206a0..e013313b9 100644
lock_keys_file();
return r;
}
-@@ -5226,7 +5493,7 @@ bool wallet2::verify_password(const epee::wipeable_string& password)
+@@ -5120,7 +5388,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
*
*/
@@ -1949,7 +1916,7 @@ index dfcc206a0..e013313b9 100644
{
rapidjson::Document json;
wallet2::keys_file_data keys_file_data;
-@@ -5243,9 +5510,22 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
+@@ -5137,9 +5405,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]);
@@ -1973,7 +1940,7 @@ index dfcc206a0..e013313b9 100644
// The contents should be JSON if the wallet follows the new format.
if (json.Parse(account_data.c_str()).HasParseError())
{
-@@ -5270,6 +5550,7 @@ bool wallet2::verify_password(const std::string& keys_file_name, const epee::wip
+@@ -5164,6 +5445,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);
@@ -1981,7 +1948,7 @@ index dfcc206a0..e013313b9 100644
return r;
}
-@@ -5281,9 +5562,7 @@ void wallet2::encrypt_keys(const crypto::chacha_key &key)
+@@ -5175,9 +5457,7 @@ void wallet2::encrypt_keys(const crypto::chacha_key &key)
void wallet2::decrypt_keys(const crypto::chacha_key &key)
{
@@ -1992,7 +1959,7 @@ index dfcc206a0..e013313b9 100644
m_account.encrypt_viewkey(key);
m_account.decrypt_keys(key);
-@@ -6001,11 +6280,30 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin
+@@ -5853,11 +6133,30 @@ void wallet2::rewrite(const std::string& wallet_name, const epee::wipeable_strin
{
if (wallet_name.empty())
return;
@@ -2023,7 +1990,7 @@ index dfcc206a0..e013313b9 100644
}
/*!
* \brief Writes to a file named based on the normal wallet (doesn't generate key, assumes it's already there)
-@@ -6348,6 +6646,16 @@ bool wallet2::wallet_valid_path_format(const std::string& file_path)
+@@ -5891,6 +6190,16 @@ bool wallet2::wallet_valid_path_format(const std::string& file_path)
return !file_path.empty();
}
//----------------------------------------------------------------------------------------------------
@@ -2040,7 +2007,7 @@ index dfcc206a0..e013313b9 100644
bool wallet2::parse_long_payment_id(const std::string& payment_id_str, crypto::hash& payment_id)
{
cryptonote::blobdata payment_id_data;
-@@ -6583,10 +6891,81 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
+@@ -6126,10 +6435,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");
}
@@ -2123,7 +2090,7 @@ index dfcc206a0..e013313b9 100644
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
+@@ -6143,7 +6523,7 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
bool r = true;
if (use_fs)
{
@@ -2132,7 +2099,7 @@ index dfcc206a0..e013313b9 100644
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
+@@ -6156,7 +6536,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());
@@ -2141,7 +2108,7 @@ index dfcc206a0..e013313b9 100644
try {
bool loaded = false;
-@@ -6703,60 +7082,76 @@ void wallet2::load(const std::string& wallet_, const epee::wipeable_string& pass
+@@ -6246,60 +6626,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);
}
@@ -2260,7 +2227,7 @@ index dfcc206a0..e013313b9 100644
}
}
//----------------------------------------------------------------------------------------------------
-@@ -6838,6 +7233,8 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
+@@ -6381,6 +6777,8 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
same_file = canonical_old_path == canonical_new_path;
}
@@ -2269,7 +2236,7 @@ index dfcc206a0..e013313b9 100644
if (!same_file)
{
-@@ -6854,6 +7251,21 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
+@@ -6397,6 +6795,21 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
}
}
}
@@ -2291,7 +2258,7 @@ index dfcc206a0..e013313b9 100644
// get wallet cache data
boost::optional<wallet2::cache_file_data> cache_file_data = get_cache_file_data();
-@@ -6947,6 +7359,22 @@ void wallet2::store_to(const std::string &path, const epee::wipeable_string &pas
+@@ -6490,6 +6903,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);
}
@@ -2314,7 +2281,7 @@ index dfcc206a0..e013313b9 100644
}
//----------------------------------------------------------------------------------------------------
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()
+@@ -6507,7 +6936,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>();
@@ -2323,7 +2290,7 @@ index dfcc206a0..e013313b9 100644
cache_file_data.get().cache_data = cipher;
return cache_file_data;
}
-@@ -9034,6 +9462,34 @@ bool wallet2::is_keys_file_locked() const
+@@ -8577,6 +9006,34 @@ bool wallet2::is_keys_file_locked() const
return m_keys_file_locker->locked();
}
@@ -2358,7 +2325,7 @@ index dfcc206a0..e013313b9 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 +14836,413 @@ bool wallet2::import_key_images(signed_tx_set & signed_tx, size_t offset, bool o
+@@ -13900,6 +14357,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);
}
@@ -2773,10 +2740,10 @@ index dfcc206a0..e013313b9 100644
{
payment_container payments;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
-index db5c1feb3..009dce766 100644
+index 75137237b..295976b53 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
-@@ -257,6 +257,20 @@ private:
+@@ -256,6 +256,20 @@ private:
BackgroundMiningNo = 2,
};
@@ -2797,7 +2764,7 @@ index db5c1feb3..009dce766 100644
enum ExportFormat {
Binary = 0,
Ascii,
-@@ -283,7 +297,12 @@ private:
+@@ -282,7 +296,12 @@ private:
//! Just parses variables.
static std::unique_ptr<wallet2> make_dummy(const boost::program_options::variables_map& vm, bool unattended, const std::function<boost::optional<password_container>(const char *, bool)> &password_prompter);
@@ -2811,7 +2778,7 @@ index db5c1feb3..009dce766 100644
static bool query_device(hw::device::device_type& device_type, const std::string& keys_file_name, const epee::wipeable_string& password, uint64_t kdf_rounds = 1);
wallet2(cryptonote::network_type nettype = cryptonote::MAINNET, uint64_t kdf_rounds = 1, bool unattended = false, std::unique_ptr<epee::net_utils::http::http_client_factory> http_client_factory = std::unique_ptr<epee::net_utils::http::http_client_factory>(new net::http::client_factory()));
-@@ -793,6 +812,54 @@ private:
+@@ -792,6 +811,54 @@ private:
END_SERIALIZE()
};
@@ -2866,7 +2833,7 @@ index db5c1feb3..009dce766 100644
typedef std::tuple<uint64_t, crypto::public_key, rct::key> get_outs_entry;
struct parsed_block
-@@ -989,7 +1056,8 @@ private:
+@@ -974,7 +1041,8 @@ private:
/*!
* \brief verifies given password is correct for default wallet keys file
*/
@@ -2876,7 +2843,7 @@ index db5c1feb3..009dce766 100644
cryptonote::account_base& get_account(){return m_account;}
const cryptonote::account_base& get_account()const{return m_account;}
-@@ -1094,6 +1162,7 @@ private:
+@@ -1069,6 +1137,7 @@ private:
cryptonote::network_type nettype() const { return m_nettype; }
bool watch_only() const { return m_watch_only; }
bool multisig(bool *ready = NULL, uint32_t *threshold = NULL, uint32_t *total = NULL) const;
@@ -2884,7 +2851,7 @@ index db5c1feb3..009dce766 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,11 +1370,17 @@ private:
+@@ -1276,11 +1345,17 @@ private:
return;
}
a & m_has_ever_refreshed_from_node;
@@ -2903,7 +2870,7 @@ index db5c1feb3..009dce766 100644
FIELD(m_blockchain)
FIELD(m_transfers)
FIELD(m_account_public_address)
-@@ -1337,6 +1412,12 @@ private:
+@@ -1312,6 +1387,12 @@ private:
return true;
}
FIELD(m_has_ever_refreshed_from_node)
@@ -2916,7 +2883,7 @@ index db5c1feb3..009dce766 100644
END_SERIALIZE()
/*!
-@@ -1352,6 +1433,8 @@ private:
+@@ -1327,6 +1408,8 @@ private:
* \return Whether path is valid format
*/
static bool wallet_valid_path_format(const std::string& file_path);
@@ -2925,7 +2892,7 @@ index db5c1feb3..009dce766 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 +1483,9 @@ private:
+@@ -1375,6 +1458,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; }
@@ -2934,10 +2901,10 @@ index db5c1feb3..009dce766 100644
+ bool is_background_syncing() const { return m_background_syncing; }
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; }
-@@ -1739,6 +1825,9 @@ private:
- std::string printPaymentDetails(const payment_details &pd);
- std::string printTxDestinationEntry(const cryptonote::tx_destination_entry &tx);
+ BackgroundMiningSetupType setup_background_mining() const { return m_setup_background_mining; }
+@@ -1689,6 +1775,9 @@ private:
+ uint64_t get_bytes_sent() const;
+ uint64_t get_bytes_received() const;
+ void start_background_sync();
+ void stop_background_sync(const epee::wipeable_string &wallet_password, const crypto::secret_key &spend_secret_key = crypto::null_skey);
@@ -2945,7 +2912,7 @@ index db5c1feb3..009dce766 100644
// MMS -------------------------------------------------------------------------------------------------
mms::message_store& get_message_store() { return m_message_store; };
const mms::message_store& get_message_store() const { return m_message_store; };
-@@ -1775,6 +1864,9 @@ private:
+@@ -1724,6 +1813,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);
@@ -2955,7 +2922,7 @@ index db5c1feb3..009dce766 100644
/*!
* \brief Load wallet keys information from wallet file.
* \param keys_file_name Name of wallet file
-@@ -1788,6 +1880,7 @@ private:
+@@ -1737,6 +1829,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);
@@ -2963,7 +2930,7 @@ index db5c1feb3..009dce766 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 +1889,15 @@ private:
+@@ -1745,6 +1838,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);
@@ -2979,7 +2946,7 @@ index db5c1feb3..009dce766 100644
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 +1949,23 @@ private:
+@@ -1796,10 +1898,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);
@@ -3003,16 +2970,16 @@ index db5c1feb3..009dce766 100644
void register_devices();
hw::device& lookup_device(const std::string & device_descriptor);
-@@ -1966,6 +2081,8 @@ private:
+@@ -1914,6 +2029,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_show_wallet_name_when_locked;
- bool m_show_detailed_prompt;
uint32_t m_inactivity_lock_timeout;
-@@ -2012,6 +2129,7 @@ private:
+ BackgroundMiningSetupType m_setup_background_mining;
+@@ -1959,6 +2076,7 @@ private:
uint64_t m_last_block_reward;
std::unique_ptr<tools::file_locker> m_keys_file_locker;
@@ -3020,7 +2987,7 @@ index db5c1feb3..009dce766 100644
mms::message_store m_message_store;
bool m_original_keys_available;
-@@ -2019,6 +2137,7 @@ private:
+@@ -1966,6 +2084,7 @@ private:
crypto::secret_key m_original_view_secret_key;
crypto::chacha_key m_cache_key;
@@ -3028,7 +2995,7 @@ index db5c1feb3..009dce766 100644
std::shared_ptr<wallet_keys_unlocker> m_encrypt_keys_after_refresh;
bool m_unattended;
-@@ -2034,9 +2153,13 @@ private:
+@@ -1981,9 +2100,13 @@ private:
static boost::mutex default_daemon_address_lock;
static std::string default_daemon_address;
@@ -3043,7 +3010,7 @@ index db5c1feb3..009dce766 100644
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 +2175,8 @@ BOOST_CLASS_VERSION(tools::wallet2::signed_tx_set, 1)
+@@ -1999,6 +2122,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)
@@ -3052,7 +3019,7 @@ index db5c1feb3..009dce766 100644
namespace boost
{
-@@ -2550,6 +2675,29 @@ namespace boost
+@@ -2497,6 +2622,29 @@ namespace boost
return;
a & x.multisig_sigs;
}
@@ -3083,7 +3050,7 @@ index db5c1feb3..009dce766 100644
}
diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h
-index 1f7e1c75d..d17b721a9 100644
+index c077313d4..c54cd3499 100644
--- a/src/wallet/wallet_errors.h
+++ b/src/wallet/wallet_errors.h
@@ -63,6 +63,7 @@ namespace tools
@@ -3094,7 +3061,7 @@ index 1f7e1c75d..d17b721a9 100644
// refresh_error *
// acc_outs_lookup_error
// block_parse_error
-@@ -96,6 +97,9 @@ namespace tools
+@@ -97,6 +98,9 @@ namespace tools
// wallet_files_doesnt_correspond
// scan_tx_error *
// wont_reprocess_recent_txs_via_untrusted_daemon
@@ -3104,7 +3071,7 @@ index 1f7e1c75d..d17b721a9 100644
//
// * - class with protected ctor
-@@ -303,6 +307,16 @@ namespace tools
+@@ -304,6 +308,16 @@ namespace tools
std::string to_string() const { return wallet_logic_error::to_string(); }
};
@@ -3121,7 +3088,7 @@ index 1f7e1c75d..d17b721a9 100644
//----------------------------------------------------------------------------------------------------
struct invalid_pregenerated_random : public wallet_logic_error
{
-@@ -944,6 +958,31 @@ namespace tools
+@@ -947,6 +961,31 @@ namespace tools
}
};
//----------------------------------------------------------------------------------------------------
@@ -3154,7 +3121,7 @@ index 1f7e1c75d..d17b721a9 100644
#if !defined(_MSC_VER)
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
-index 3bb045b6a..8d2c68ac4 100644
+index 6fc996299..3cc6b278f 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -73,6 +73,54 @@ using namespace epee;
@@ -3319,7 +3286,7 @@ index 3bb045b6a..8d2c68ac4 100644
crypto::hash8 integrated_payment_id = crypto::null_hash8;
std::string extra_nonce;
for (auto it = destinations.begin(); it != destinations.end(); it++)
-@@ -1191,6 +1255,7 @@ namespace tools
+@@ -1203,6 +1267,7 @@ namespace tools
}
CHECK_MULTISIG_ENABLED();
@@ -3327,7 +3294,7 @@ index 3bb045b6a..8d2c68ac4 100644
cryptonote::blobdata blob;
if (!epee::string_tools::parse_hexstr_to_binbuff(req.unsigned_txset, blob))
-@@ -1272,6 +1337,7 @@ namespace tools
+@@ -1284,6 +1349,7 @@ namespace tools
er.message = "command not supported by watch-only wallet";
return false;
}
@@ -3335,7 +3302,7 @@ index 3bb045b6a..8d2c68ac4 100644
if(req.unsigned_txset.empty() && req.multisig_txset.empty())
{
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
-@@ -1541,6 +1607,7 @@ namespace tools
+@@ -1553,6 +1619,7 @@ namespace tools
}
CHECK_MULTISIG_ENABLED();
@@ -3343,7 +3310,7 @@ index 3bb045b6a..8d2c68ac4 100644
try
{
-@@ -2090,6 +2157,7 @@ namespace tools
+@@ -2114,6 +2181,7 @@ namespace tools
er.message = "The wallet is watch-only. Cannot retrieve seed.";
return false;
}
@@ -3351,7 +3318,7 @@ index 3bb045b6a..8d2c68ac4 100644
if (!m_wallet->is_deterministic())
{
er.code = WALLET_RPC_ERROR_CODE_NON_DETERMINISTIC;
-@@ -2118,6 +2186,7 @@ namespace tools
+@@ -2142,6 +2210,7 @@ namespace tools
er.message = "The wallet is watch-only. Cannot retrieve spend key.";
return false;
}
@@ -3359,7 +3326,7 @@ index 3bb045b6a..8d2c68ac4 100644
epee::wipeable_string key = epee::to_hex::wipeable_string(m_wallet->get_account().get_keys().m_spend_secret_key);
res.key = std::string(key.data(), key.size());
}
-@@ -2139,6 +2208,7 @@ namespace tools
+@@ -2163,6 +2232,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
@@ -3367,7 +3334,7 @@ index 3bb045b6a..8d2c68ac4 100644
try
{
-@@ -2152,6 +2222,79 @@ namespace tools
+@@ -2176,6 +2246,79 @@ namespace tools
return true;
}
//------------------------------------------------------------------------------------------------------------------------------
@@ -3447,7 +3414,7 @@ index 3bb045b6a..8d2c68ac4 100644
bool wallet_rpc_server::on_sign(const wallet_rpc::COMMAND_RPC_SIGN::request& req, wallet_rpc::COMMAND_RPC_SIGN::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
if (!m_wallet) return not_open(er);
-@@ -2161,6 +2304,7 @@ namespace tools
+@@ -2185,6 +2328,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
@@ -3455,7 +3422,7 @@ index 3bb045b6a..8d2c68ac4 100644
tools::wallet2::message_signature_type_t signature_type = tools::wallet2::sign_with_spend_key;
if (req.signature_type == "spend" || req.signature_type == "")
-@@ -2253,6 +2397,7 @@ namespace tools
+@@ -2277,6 +2421,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
@@ -3463,7 +3430,7 @@ index 3bb045b6a..8d2c68ac4 100644
if (req.txids.size() != req.notes.size())
{
-@@ -2325,6 +2470,7 @@ namespace tools
+@@ -2349,6 +2494,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
@@ -3471,7 +3438,7 @@ index 3bb045b6a..8d2c68ac4 100644
m_wallet->set_attribute(req.key, req.value);
-@@ -2352,6 +2498,7 @@ namespace tools
+@@ -2376,6 +2522,7 @@ namespace tools
bool wallet_rpc_server::on_get_tx_key(const wallet_rpc::COMMAND_RPC_GET_TX_KEY::request& req, wallet_rpc::COMMAND_RPC_GET_TX_KEY::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
if (!m_wallet) return not_open(er);
@@ -3479,7 +3446,7 @@ index 3bb045b6a..8d2c68ac4 100644
crypto::hash txid;
if (!epee::string_tools::hex_to_pod(req.txid, txid))
-@@ -2443,6 +2590,7 @@ namespace tools
+@@ -2467,6 +2614,7 @@ namespace tools
bool wallet_rpc_server::on_get_tx_proof(const wallet_rpc::COMMAND_RPC_GET_TX_PROOF::request& req, wallet_rpc::COMMAND_RPC_GET_TX_PROOF::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
if (!m_wallet) return not_open(er);
@@ -3487,7 +3454,7 @@ index 3bb045b6a..8d2c68ac4 100644
crypto::hash txid;
if (!epee::string_tools::hex_to_pod(req.txid, txid))
-@@ -2559,6 +2707,7 @@ namespace tools
+@@ -2583,6 +2731,7 @@ namespace tools
bool wallet_rpc_server::on_get_reserve_proof(const wallet_rpc::COMMAND_RPC_GET_RESERVE_PROOF::request& req, wallet_rpc::COMMAND_RPC_GET_RESERVE_PROOF::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
if (!m_wallet) return not_open(er);
@@ -3495,7 +3462,7 @@ index 3bb045b6a..8d2c68ac4 100644
boost::optional<std::pair<uint32_t, uint64_t>> account_minreserve;
if (!req.all)
-@@ -2801,6 +2950,7 @@ namespace tools
+@@ -2825,6 +2974,7 @@ namespace tools
er.message = "command not supported by HW wallet";
return false;
}
@@ -3503,7 +3470,7 @@ index 3bb045b6a..8d2c68ac4 100644
try
{
-@@ -2830,6 +2980,7 @@ namespace tools
+@@ -2854,6 +3004,7 @@ namespace tools
er.message = "command not supported by HW wallet";
return false;
}
@@ -3511,7 +3478,7 @@ index 3bb045b6a..8d2c68ac4 100644
cryptonote::blobdata blob;
if (!epee::string_tools::parse_hexstr_to_binbuff(req.outputs_data_hex, blob))
-@@ -2855,6 +3006,7 @@ namespace tools
+@@ -2879,6 +3030,7 @@ namespace tools
bool wallet_rpc_server::on_export_key_images(const wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES::request& req, wallet_rpc::COMMAND_RPC_EXPORT_KEY_IMAGES::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
if (!m_wallet) return not_open(er);
@@ -3519,7 +3486,7 @@ index 3bb045b6a..8d2c68ac4 100644
try
{
std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = m_wallet->export_key_images(req.all);
-@@ -2891,6 +3043,7 @@ namespace tools
+@@ -2915,6 +3067,7 @@ namespace tools
er.message = "This command requires a trusted daemon.";
return false;
}
@@ -3527,7 +3494,7 @@ index 3bb045b6a..8d2c68ac4 100644
try
{
std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
-@@ -2959,6 +3112,7 @@ namespace tools
+@@ -2983,6 +3136,7 @@ namespace tools
bool wallet_rpc_server::on_get_address_book(const wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::request& req, wallet_rpc::COMMAND_RPC_GET_ADDRESS_BOOK_ENTRY::response& res, epee::json_rpc::error& er, const connection_context *ctx)
{
if (!m_wallet) return not_open(er);
@@ -3535,7 +3502,7 @@ index 3bb045b6a..8d2c68ac4 100644
const auto ab = m_wallet->get_address_book();
if (req.entries.empty())
{
-@@ -3004,6 +3158,7 @@ namespace tools
+@@ -3028,6 +3182,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
@@ -3543,7 +3510,7 @@ index 3bb045b6a..8d2c68ac4 100644
cryptonote::address_parse_info info;
er.message = "";
-@@ -3046,6 +3201,7 @@ namespace tools
+@@ -3070,6 +3225,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
@@ -3551,7 +3518,7 @@ index 3bb045b6a..8d2c68ac4 100644
const auto ab = m_wallet->get_address_book();
if (req.index >= ab.size())
-@@ -3108,6 +3264,7 @@ namespace tools
+@@ -3132,6 +3288,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
@@ -3559,7 +3526,7 @@ index 3bb045b6a..8d2c68ac4 100644
const auto ab = m_wallet->get_address_book();
if (req.index >= ab.size())
-@@ -3178,6 +3335,7 @@ namespace tools
+@@ -3202,6 +3359,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
@@ -3567,7 +3534,7 @@ index 3bb045b6a..8d2c68ac4 100644
std::unordered_set<crypto::hash> txids;
std::list<std::string>::const_iterator i = req.txids.begin();
-@@ -3217,6 +3375,7 @@ namespace tools
+@@ -3241,6 +3399,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
@@ -3575,7 +3542,7 @@ index 3bb045b6a..8d2c68ac4 100644
try
{
m_wallet->rescan_spent();
-@@ -3481,6 +3640,7 @@ namespace tools
+@@ -3505,6 +3664,7 @@ namespace tools
er.message = "Command unavailable in restricted mode.";
return false;
}
@@ -3583,7 +3550,7 @@ index 3bb045b6a..8d2c68ac4 100644
if (m_wallet->verify_password(req.old_password))
{
try
-@@ -4008,6 +4168,7 @@ namespace tools
+@@ -4032,6 +4192,7 @@ namespace tools
er.message = "wallet is watch-only and cannot be made multisig";
return false;
}
@@ -3591,7 +3558,7 @@ index 3bb045b6a..8d2c68ac4 100644
res.multisig_info = m_wallet->get_multisig_first_kex_msg();
return true;
-@@ -4035,6 +4196,7 @@ namespace tools
+@@ -4059,6 +4220,7 @@ namespace tools
er.message = "wallet is watch-only and cannot be made multisig";
return false;
}
@@ -3698,15 +3665,15 @@ index b6098d95c..a44b56ed6 100644
}
}
diff --git a/src/wallet/wallet_rpc_server_error_codes.h b/src/wallet/wallet_rpc_server_error_codes.h
-index 734229380..b964036bd 100644
+index 541d29f86..4756c191c 100644
--- a/src/wallet/wallet_rpc_server_error_codes.h
+++ b/src/wallet/wallet_rpc_server_error_codes.h
-@@ -79,3 +79,5 @@
- #define WALLET_RPC_ERROR_CODE_ZERO_AMOUNT -46
- #define WALLET_RPC_ERROR_CODE_INVALID_SIGNATURE_TYPE -47
+@@ -81,3 +81,5 @@
#define WALLET_RPC_ERROR_CODE_DISABLED -48
-+#define WALLET_RPC_ERROR_CODE_IS_BACKGROUND_WALLET -49
-+#define WALLET_RPC_ERROR_CODE_IS_BACKGROUND_SYNCING -50
+ #define WALLET_RPC_ERROR_CODE_PROXY_ALREADY_DEFINED -49
+ #define WALLET_RPC_ERROR_CODE_NONZERO_UNLOCK_TIME -50
++#define WALLET_RPC_ERROR_CODE_IS_BACKGROUND_WALLET -51
++#define WALLET_RPC_ERROR_CODE_IS_BACKGROUND_SYNCING -52
diff --git a/tests/functional_tests/transfer.py b/tests/functional_tests/transfer.py
index 4063911f4..60eb09a10 100755
--- a/tests/functional_tests/transfer.py
@@ -4347,5 +4314,5 @@ index 1e10e1f86..bff33a561 100644
+ }
+ return self.rpc.send_json_rpc_request(stop_background_sync)
--
-2.45.2
+2.39.5 (Apple Git-154)
diff --git a/patches/wownero/0002-fix-missing-___clear_cache-when-targetting-iOS.patch b/patches/wownero/0002-fix-missing-___clear_cache-when-targetting-iOS.patch
new file mode 100644
index 0000000..d922a40
--- /dev/null
+++ b/patches/wownero/0002-fix-missing-___clear_cache-when-targetting-iOS.patch
@@ -0,0 +1,19 @@
+From 21e95275c2e40454d9cce05c1139d8139af16587 Mon Sep 17 00:00:00 2001
+From: Czarek Nakamoto <cyjan@mrcyjanek.net>
+Date: Wed, 23 Oct 2024 15:18:21 +0200
+Subject: [PATCH 02/15] fix missing ___clear_cache when targetting iOS
+
+---
+ external/randomwow | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/external/randomwow b/external/randomwow
+index 27b099b6d..c00685dad 160000
+--- a/external/randomwow
++++ b/external/randomwow
+@@ -1 +1 @@
+-Subproject commit 27b099b6dd6fef6e17f58c6dfe00009e9c5df587
++Subproject commit c00685dad575137caf4a9100ba08e77be376fa98
+--
+2.39.5 (Apple Git-154)
+
diff --git a/patches/wownero/0003-fix-is_trivially_copyable.patch b/patches/wownero/0003-fix-is_trivially_copyable.patch
new file mode 100644
index 0000000..f600003
--- /dev/null
+++ b/patches/wownero/0003-fix-is_trivially_copyable.patch
@@ -0,0 +1,32 @@
+From b41551e7dd8d3f4968f330f60d14773eaabca818 Mon Sep 17 00:00:00 2001
+From: cyan <cyjan@mrcyjanek.net>
+Date: Tue, 22 Oct 2024 10:23:18 +0000
+Subject: [PATCH 03/15] fix is_trivially_copyable
+
+---
+ contrib/epee/include/span.h | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/contrib/epee/include/span.h b/contrib/epee/include/span.h
+index 01dc387d6..5e3af4d11 100644
+--- a/contrib/epee/include/span.h
++++ b/contrib/epee/include/span.h
+@@ -151,7 +151,6 @@ namespace epee
+ using value_type = typename T::value_type;
+ static_assert(!std::is_empty<value_type>(), "empty value types will not work -> sizeof == 1");
+ static_assert(std::is_standard_layout<value_type>(), "value type must have standard layout");
+- static_assert(std::is_trivially_copyable<value_type>(), "value type must be trivially copyable");
+ static_assert(alignof(value_type) == 1, "value type may have padding");
+ return {reinterpret_cast<std::uint8_t*>(src.data()), src.size() * sizeof(value_type)};
+ }
+@@ -162,7 +161,6 @@ namespace epee
+ {
+ static_assert(!std::is_empty<T>(), "empty types will not work -> sizeof == 1");
+ static_assert(std::is_standard_layout<T>(), "type must have standard layout");
+- static_assert(std::is_trivially_copyable<T>(), "type must be trivially copyable");
+ static_assert(alignof(T) == 1, "type may have padding");
+ return {reinterpret_cast<const std::uint8_t*>(std::addressof(src)), sizeof(T)};
+ }
+--
+2.39.5 (Apple Git-154)
+
diff --git a/patches/wownero/0004-airgap.patch b/patches/wownero/0004-airgap.patch
deleted file mode 100644
index 4bdd4ef..0000000
--- a/patches/wownero/0004-airgap.patch
+++ /dev/null
@@ -1,170 +0,0 @@
-From dd3b82ecf391fbaa91d16634198e58fa9ed0091f Mon Sep 17 00:00:00 2001
-From: tobtoht <tob@featherwallet.org>
-Date: Tue, 26 Mar 2024 09:06:32 +0100
-Subject: [PATCH 04/14] airgap
-
----
- 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.h | 1 +
- 5 files changed, 51 insertions(+), 6 deletions(-)
-
-diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index 27a4dc6c8..4b2693f23 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
- return m_wallet->unlocked_balance(accountIndex, false);
- }
-
-+uint64_t WalletImpl::viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images) const
-+{
-+ clearStatus();
-+
-+ std::vector<crypto::key_image> kis;
-+ for (const auto &key_image : key_images) {
-+ crypto::key_image ki;
-+ if (!epee::string_tools::hex_to_pod(key_image, ki))
-+ {
-+ setStatusError(tr("failed to parse key image"));
-+ return 0;
-+ }
-+ kis.push_back(ki);
-+ }
-+
-+ return m_wallet->view_only_balance(accountIndex, kis);
-+}
-+
- uint64_t WalletImpl::blockChainHeight() const
- {
- if(m_wallet->light_wallet()) {
-@@ -1376,6 +1394,11 @@ bool WalletImpl::submitTransaction(const string &fileName) {
- return true;
- }
-
-+bool WalletImpl::hasUnknownKeyImages() const
-+{
-+ return m_wallet->has_unknown_key_images();
-+}
-+
- bool WalletImpl::exportKeyImages(const string &filename, bool all)
- {
- if (m_wallet->watch_only())
-diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
-index fc6341861..7b885e866 100644
---- a/src/wallet/api/wallet.h
-+++ b/src/wallet/api/wallet.h
-@@ -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;
-+ uint64_t viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images) const override;
- uint64_t blockChainHeight() const override;
- uint64_t approximateBlockChainHeight() const override;
- uint64_t estimateBlockChainHeight() const 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;
-diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
-index db5509227..5dcaeaaab 100644
---- a/src/wallet/api/wallet2_api.h
-+++ b/src/wallet/api/wallet2_api.h
-@@ -726,6 +726,7 @@ struct Wallet
- result += unlockedBalance(i);
- return result;
- }
-+ virtual uint64_t viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images = {}) const = 0;
-
- /**
- * @brief watchOnly - checks if wallet is watch only
-@@ -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;
-
-+ virtual bool hasUnknownKeyImages() const = 0;
-+
- /*!
- * \brief exportKeyImages - exports key images to file
- * \param filename
-diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
-index e013313b9..2a5f17a9f 100644
---- a/src/wallet/wallet2.cpp
-+++ b/src/wallet/wallet2.cpp
-@@ -7432,6 +7432,25 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t *
- return amount;
- }
- //----------------------------------------------------------------------------------------------------
-+uint64_t wallet2::view_only_balance(uint32_t index_major, const std::vector<crypto::key_image>& selected_inputs)
-+{
-+ uint64_t amount = 0;
-+ for (const auto &td : m_transfers) {
-+ if (is_preferred_input(selected_inputs, td.m_key_image) &&
-+ !is_spent(td, false) &&
-+ !td.m_frozen &&
-+ !td.m_key_image_partial &&
-+ td.m_key_image_known &&
-+ td.is_rct() &&
-+ is_transfer_unlocked(td) &&
-+ td.m_subaddr_index.major == index_major)
-+ {
-+ amount += td.m_amount;
-+ }
-+ }
-+ return amount;
-+}
-+//----------------------------------------------------------------------------------------------------
- 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;
-@@ -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;
-
-- // compute public keys from out secret keys
-- crypto::public_key tx_pub_key;
-- crypto::secret_key_to_public_key(txs[n].tx_key, tx_pub_key);
-+ crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx);
- std::vector<crypto::public_key> additional_tx_pub_keys;
- for (const crypto::secret_key &skey: txs[n].additional_tx_keys)
- {
-@@ -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;
- }
-- if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
-+ if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && td.m_key_image_known && (use_rct ? true : !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)
- {
-@@ -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");
-
-- if (unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty())
-- return std::vector<wallet2::pending_tx>();
-+ THROW_WALLET_EXCEPTION_IF(unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty(), error::wallet_internal_error, "No enotes available to spend")
-
- // 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 009dce766..294a2d1f6 100644
---- a/src/wallet/wallet2.h
-+++ b/src/wallet/wallet2.h
-@@ -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);
-+ uint64_t view_only_balance(uint32_t index_major, const std::vector<crypto::key_image>& selected_inputs = {});
- // 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.45.2
-
diff --git a/patches/monero/0011-store-crash-fix.patch b/patches/wownero/0004-store-crash-fix.patch
index 1ddae67..0f15183 100644
--- a/patches/monero/0011-store-crash-fix.patch
+++ b/patches/wownero/0004-store-crash-fix.patch
@@ -1,7 +1,7 @@
-From 238c847c153c74953b094d83bfe181a596771d37 Mon Sep 17 00:00:00 2001
+From 9dc9c8048d3918fe3615e91ab8be342471167c26 Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Sat, 11 May 2024 16:25:10 +0200
-Subject: [PATCH 11/16] store crash fix
+Subject: [PATCH 04/15] store crash fix
Monero wallet crashes (sometimes) when it is syncing,
while the proper solution (that can be seen in feather)
@@ -43,10 +43,10 @@ the current state.
4 files changed, 26 insertions(+), 15 deletions(-)
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index ec4ae51ff..306c9b8ae 100644
+index e868fa039..899ef044a 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
-@@ -56,8 +56,8 @@ using namespace cryptonote;
+@@ -55,8 +55,8 @@ using namespace cryptonote;
#define MONERO_DEFAULT_LOG_CATEGORY "WalletAPI"
#define LOCK_REFRESH() \
@@ -57,7 +57,7 @@ index ec4ae51ff..306c9b8ae 100644
m_wallet->stop(); \
m_refreshCV.notify_one(); \
boost::mutex::scoped_lock lock(m_refreshMutex); \
-@@ -467,7 +467,7 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds)
+@@ -466,7 +466,7 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds)
m_wallet2Callback.reset(new Wallet2CallbackImpl(this));
m_wallet->callback(m_wallet2Callback.get());
m_refreshThreadDone = false;
@@ -65,8 +65,8 @@ index ec4ae51ff..306c9b8ae 100644
+ m_wallet->set_refresh_enabled(false);
m_addressBook.reset(new AddressBookImpl(this));
m_subaddress.reset(new SubaddressImpl(this));
- m_coins.reset(new CoinsImpl(this));
-@@ -1064,6 +1064,7 @@ void WalletImpl::stop()
+ m_subaddressAccount.reset(new SubaddressAccountImpl(this));
+@@ -962,6 +962,7 @@ void WalletImpl::stop()
bool WalletImpl::store(const std::string &path)
{
clearStatus();
@@ -74,7 +74,7 @@ index ec4ae51ff..306c9b8ae 100644
try {
if (path.empty()) {
m_wallet->store();
-@@ -2591,10 +2592,10 @@ void WalletImpl::refreshThreadFunc()
+@@ -2448,10 +2449,10 @@ void WalletImpl::refreshThreadFunc()
}
LOG_PRINT_L3(__FUNCTION__ << ": refresh lock acquired...");
@@ -87,7 +87,7 @@ index ec4ae51ff..306c9b8ae 100644
LOG_PRINT_L3(__FUNCTION__ << ": refreshing...");
doRefresh();
}
-@@ -2624,12 +2625,12 @@ void WalletImpl::doRefresh()
+@@ -2481,12 +2482,12 @@ void WalletImpl::doRefresh()
}
m_wallet->find_and_save_rings(false);
} else {
@@ -102,7 +102,7 @@ index ec4ae51ff..306c9b8ae 100644
if (m_wallet2Callback->getListener()) {
m_wallet2Callback->getListener()->refreshed();
-@@ -2639,9 +2640,9 @@ void WalletImpl::doRefresh()
+@@ -2496,9 +2497,9 @@ void WalletImpl::doRefresh()
void WalletImpl::startRefresh()
{
@@ -114,7 +114,7 @@ index ec4ae51ff..306c9b8ae 100644
m_refreshCV.notify_one();
}
}
-@@ -2651,7 +2652,7 @@ void WalletImpl::startRefresh()
+@@ -2508,7 +2509,7 @@ void WalletImpl::startRefresh()
void WalletImpl::stopRefresh()
{
if (!m_refreshThreadDone) {
@@ -123,7 +123,7 @@ index ec4ae51ff..306c9b8ae 100644
m_refreshThreadDone = true;
m_refreshCV.notify_one();
m_refreshThread.join();
-@@ -2662,9 +2663,7 @@ void WalletImpl::pauseRefresh()
+@@ -2519,9 +2520,7 @@ void WalletImpl::pauseRefresh()
{
LOG_PRINT_L2(__FUNCTION__ << ": refresh paused...");
// TODO synchronize access
@@ -135,10 +135,10 @@ index ec4ae51ff..306c9b8ae 100644
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
-index d0f443abc..2ad2b62a4 100644
+index 1f199a72c..ac7ce2f6a 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
-@@ -295,7 +295,6 @@ private:
+@@ -273,7 +273,6 @@ private:
std::unique_ptr<SubaddressAccountImpl> m_subaddressAccount;
// multi-threaded refresh stuff
@@ -147,10 +147,10 @@ index d0f443abc..2ad2b62a4 100644
std::atomic<int> m_refreshIntervalMillis;
std::atomic<bool> m_refreshShouldRescan;
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
-index 61601f70c..4de226a4a 100644
+index 8ce515c57..651161d14 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
-@@ -1203,6 +1203,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
+@@ -1192,6 +1192,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
m_upper_transaction_weight_limit(0),
m_run(true),
m_callback(0),
@@ -158,7 +158,7 @@ index 61601f70c..4de226a4a 100644
m_trusted_daemon(false),
m_nettype(nettype),
m_multisig_rounds_passed(0),
-@@ -1416,6 +1417,14 @@ bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_u
+@@ -1404,6 +1405,14 @@ bool wallet2::set_daemon(std::string daemon_address, boost::optional<epee::net_u
return ret;
}
//----------------------------------------------------------------------------------------------------
@@ -173,7 +173,7 @@ index 61601f70c..4de226a4a 100644
bool wallet2::set_proxy(const std::string &address)
{
return m_http_client->set_proxy(address);
-@@ -4146,8 +4155,9 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
+@@ -4098,8 +4107,9 @@ void wallet2::refresh(bool trusted_daemon, uint64_t start_height, uint64_t & blo
// infer when we get an incoming output
bool first = true, last = false;
@@ -185,10 +185,10 @@ index 61601f70c..4de226a4a 100644
std::vector<cryptonote::block_complete_entry> next_blocks;
std::vector<parsed_block> next_parsed_blocks;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
-index fdc1a6212..3ce710433 100644
+index 295976b53..c07a47c11 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
-@@ -1086,6 +1086,8 @@ private:
+@@ -1071,6 +1071,8 @@ private:
boost::optional<epee::net_utils::http::login> daemon_login = boost::none, bool trusted_daemon = true,
epee::net_utils::ssl_options_t ssl_options = epee::net_utils::ssl_support_t::e_ssl_support_autodetect);
bool set_proxy(const std::string &address);
@@ -197,7 +197,7 @@ index fdc1a6212..3ce710433 100644
void stop() { m_run.store(false, std::memory_order_relaxed); m_message_store.stop(); }
-@@ -2012,6 +2014,7 @@ private:
+@@ -1981,6 +1983,7 @@ private:
boost::recursive_mutex m_daemon_rpc_mutex;
@@ -206,5 +206,5 @@ index fdc1a6212..3ce710433 100644
i_wallet2_callback* m_callback;
hw::device::device_type m_key_device_type;
--
-2.39.2
+2.39.5 (Apple Git-154)
diff --git a/patches/wownero/0005-coin-control.patch b/patches/wownero/0005-coin-control.patch
deleted file mode 100644
index 4502af5..0000000
--- a/patches/wownero/0005-coin-control.patch
+++ /dev/null
@@ -1,225 +0,0 @@
-From 820424507f43711e5e6b31a68dfda7e430cdae9d Mon Sep 17 00:00:00 2001
-From: tobtoht <tob@featherwallet.org>
-Date: Wed, 27 Mar 2024 16:31:36 +0100
-Subject: [PATCH 05/14] coin control
-
----
- src/wallet/api/coins.cpp | 62 ++++++++++++++++++++++++++++++++++++
- src/wallet/api/coins.h | 4 +++
- src/wallet/api/wallet.cpp | 4 +--
- src/wallet/api/wallet2_api.h | 3 ++
- src/wallet/wallet2.cpp | 22 +++++++++++++
- src/wallet/wallet2.h | 4 +++
- 6 files changed, 97 insertions(+), 2 deletions(-)
-
-diff --git a/src/wallet/api/coins.cpp b/src/wallet/api/coins.cpp
-index fe54b82cf..5ce69b5b9 100644
---- a/src/wallet/api/coins.cpp
-+++ b/src/wallet/api/coins.cpp
-@@ -90,6 +90,26 @@ namespace Monero {
- }
- }
-
-+ void CoinsImpl::setFrozen(std::string public_key)
-+ {
-+ crypto::public_key pk;
-+ if (!epee::string_tools::hex_to_pod(public_key, pk))
-+ {
-+ LOG_ERROR("Invalid public key: " << public_key);
-+ return;
-+ }
-+
-+ try
-+ {
-+ m_wallet->m_wallet->freeze(pk);
-+ refresh();
-+ }
-+ catch (const std::exception& e)
-+ {
-+ LOG_ERROR("setFrozen: " << e.what());
-+ }
-+ }
-+
- void CoinsImpl::setFrozen(int index)
- {
- try
-@@ -103,6 +123,26 @@ namespace Monero {
- }
- }
-
-+ void CoinsImpl::thaw(std::string public_key)
-+ {
-+ crypto::public_key pk;
-+ if (!epee::string_tools::hex_to_pod(public_key, pk))
-+ {
-+ LOG_ERROR("Invalid public key: " << public_key);
-+ return;
-+ }
-+
-+ try
-+ {
-+ m_wallet->m_wallet->thaw(pk);
-+ refresh();
-+ }
-+ catch (const std::exception& e)
-+ {
-+ LOG_ERROR("thaw: " << e.what());
-+ }
-+ }
-+
- void CoinsImpl::thaw(int index)
- {
- try
-@@ -120,4 +160,26 @@ namespace Monero {
- return m_wallet->m_wallet->is_transfer_unlocked(unlockTime, blockHeight);
- }
-
-+ void CoinsImpl::setDescription(const std::string &public_key, const std::string &description)
-+ {
-+ crypto::public_key pk;
-+ if (!epee::string_tools::hex_to_pod(public_key, pk))
-+ {
-+ LOG_ERROR("Invalid public key: " << public_key);
-+ return;
-+ }
-+
-+ try
-+ {
-+ const size_t index = m_wallet->m_wallet->get_transfer_details(pk);
-+ const tools::wallet2::transfer_details &td = m_wallet->m_wallet->get_transfer_details(index);
-+ m_wallet->m_wallet->set_tx_note(td.m_txid, description);
-+ refresh();
-+ }
-+ catch (const std::exception& e)
-+ {
-+ LOG_ERROR("setDescription: " << e.what());
-+ }
-+ }
-+
- } // namespace
-diff --git a/src/wallet/api/coins.h b/src/wallet/api/coins.h
-index 3293d8ae9..bcd8b517f 100644
---- a/src/wallet/api/coins.h
-+++ b/src/wallet/api/coins.h
-@@ -18,11 +18,15 @@ namespace Monero {
- std::vector<CoinsInfo*> getAll() const override;
- void refresh() override;
-
-+ void setFrozen(std::string public_key) override;
- void setFrozen(int index) override;
-+ void thaw(std::string public_key) override;
- void thaw(int index) override;
-
- bool isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) override;
-
-+ void setDescription(const std::string &public_key, const std::string &description) override;
-+
- private:
- WalletImpl *m_wallet;
- std::vector<CoinsInfo*> m_rows;
-diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index 4b2693f23..ed309de34 100644
---- a/src/wallet/api/wallet.cpp
-+++ b/src/wallet/api/wallet.cpp
-@@ -2018,11 +2018,11 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
- if (amount) {
- transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */,
- adjusted_priority,
-- extra, subaddr_account, subaddr_indices);
-+ extra, subaddr_account, subaddr_indices, {}, preferred_input_list);
- } else {
- transaction->m_pending_tx = m_wallet->create_transactions_all(0, info.address, info.is_subaddress, 1, fake_outs_count, 0 /* unlock_time */,
- adjusted_priority,
-- extra, subaddr_account, subaddr_indices);
-+ extra, subaddr_account, subaddr_indices, preferred_input_list);
- }
- pendingTxPostProcess(transaction);
-
-diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
-index 5dcaeaaab..347e6d002 100644
---- a/src/wallet/api/wallet2_api.h
-+++ b/src/wallet/api/wallet2_api.h
-@@ -352,9 +352,12 @@ struct Coins
- virtual CoinsInfo * coin(int index) const = 0;
- virtual std::vector<CoinsInfo*> getAll() const = 0;
- virtual void refresh() = 0;
-+ virtual void setFrozen(std::string public_key) = 0;
- virtual void setFrozen(int index) = 0;
- virtual void thaw(int index) = 0;
-+ virtual void thaw(std::string public_key) = 0;
- virtual bool isTransferUnlocked(uint64_t unlockTime, uint64_t blockHeight) = 0;
-+ virtual void setDescription(const std::string &public_key, const std::string &description) = 0;
- };
-
- struct SubaddressRow {
-diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
-index 2a5f17a9f..2b3eaad2e 100644
---- a/src/wallet/wallet2.cpp
-+++ b/src/wallet/wallet2.cpp
-@@ -2094,11 +2094,21 @@ bool wallet2::frozen(const multisig_tx_set& txs) const
- return false;
- }
- //----------------------------------------------------------------------------------------------------
-+void wallet2::freeze(const crypto::public_key &pk)
-+{
-+ freeze(get_transfer_details(pk));
-+}
-+//----------------------------------------------------------------------------------------------------
- void wallet2::freeze(const crypto::key_image &ki)
- {
- freeze(get_transfer_details(ki));
- }
- //----------------------------------------------------------------------------------------------------
-+void wallet2::thaw(const crypto::public_key &pk)
-+{
-+ thaw(get_transfer_details(pk));
-+}
-+//----------------------------------------------------------------------------------------------------
- void wallet2::thaw(const crypto::key_image &ki)
- {
- thaw(get_transfer_details(ki));
-@@ -2109,6 +2119,18 @@ bool wallet2::frozen(const crypto::key_image &ki) const
- return frozen(get_transfer_details(ki));
- }
- //----------------------------------------------------------------------------------------------------
-+size_t wallet2::get_transfer_details(const crypto::public_key &pk) const
-+{
-+ for (size_t idx = 0; idx < m_transfers.size(); ++idx)
-+ {
-+ const transfer_details &td = m_transfers[idx];
-+ if (td.get_public_key() == pk) {
-+ return idx;
-+ }
-+ }
-+ CHECK_AND_ASSERT_THROW_MES(false, "Public key not found");
-+}
-+//----------------------------------------------------------------------------------------------------
- size_t wallet2::get_transfer_details(const crypto::key_image &ki) const
- {
- for (size_t idx = 0; idx < m_transfers.size(); ++idx)
-diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
-index 294a2d1f6..d1e68baac 100644
---- a/src/wallet/wallet2.h
-+++ b/src/wallet/wallet2.h
-@@ -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;
-+ size_t get_transfer_details(const crypto::public_key &pk) const;
-+
-
- uint8_t get_current_hard_fork();
- void get_hard_fork_info(uint8_t version, uint64_t &earliest_height);
-@@ -1793,7 +1795,9 @@ private:
- void freeze(size_t idx);
- void thaw(size_t idx);
- bool frozen(size_t idx) const;
-+ void freeze(const crypto::public_key &pk);
- void freeze(const crypto::key_image &ki);
-+ void thaw(const crypto::public_key &pk);
- void thaw(const crypto::key_image &ki);
- bool frozen(const crypto::key_image &ki) const;
- bool frozen(const transfer_details &td) const;
---
-2.45.2
-
diff --git a/patches/monero/0016-uint64_t-missing-definition-fix.patch b/patches/wownero/0005-uint64_t-missing-definition-fix.patch
index e555829..05bef1f 100644
--- a/patches/monero/0016-uint64_t-missing-definition-fix.patch
+++ b/patches/wownero/0005-uint64_t-missing-definition-fix.patch
@@ -1,7 +1,7 @@
-From 9fe376e0024dfdbea47219477e797cb20c56305f Mon Sep 17 00:00:00 2001
+From 223e2e4b5b2c6366d0dd4130a726c4cfcdb13ffb Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Mon, 2 Sep 2024 16:40:31 +0200
-Subject: [PATCH] uint64_t missing definition fix
+Subject: [PATCH 05/15] uint64_t missing definition fix
---
contrib/epee/include/net/http_base.h | 2 +-
@@ -21,5 +21,5 @@ index 4af4da790..ae4c0d05e 100644
#include <string>
--
-2.43.0
+2.39.5 (Apple Git-154)
diff --git a/patches/wownero/0006-fix-build.patch b/patches/wownero/0006-fix-build.patch
deleted file mode 100644
index 0c93665..0000000
--- a/patches/wownero/0006-fix-build.patch
+++ /dev/null
@@ -1,137 +0,0 @@
-From cf12239f0c85f5865a796ac97c82f409604cfd3e Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Tue, 26 Mar 2024 09:44:54 +0100
-Subject: [PATCH 06/14] fix build
-
----
- contrib/depends/hosts/linux.mk | 8 +++----
- contrib/depends/packages/android_ndk.mk | 2 ++
- contrib/depends/packages/packages.mk | 2 +-
- contrib/depends/packages/polyseed.mk | 23 +++++++++++++++++++
- contrib/depends/packages/sodium.mk | 2 +-
- .../patches/polyseed/force-static-mingw.patch | 23 +++++++++++++++++++
- 6 files changed, 54 insertions(+), 6 deletions(-)
- create mode 100644 contrib/depends/packages/polyseed.mk
- create mode 100644 contrib/depends/patches/polyseed/force-static-mingw.patch
-
-diff --git a/contrib/depends/hosts/linux.mk b/contrib/depends/hosts/linux.mk
-index 912fdb03c..b79799f30 100644
---- a/contrib/depends/hosts/linux.mk
-+++ b/contrib/depends/hosts/linux.mk
-@@ -11,15 +11,15 @@ linux_debug_CXXFLAGS=$(linux_debug_CFLAGS)
- linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
-
- ifeq (86,$(findstring 86,$(build_arch)))
--i686_linux_CC=gcc -m32
--i686_linux_CXX=g++ -m32
-+i686_linux_CC=i686-linux-gnu-gcc
-+i686_linux_CXX=i686-linux-gnu-g++
- i686_linux_AR=ar
- i686_linux_RANLIB=ranlib
- i686_linux_NM=nm
- i686_linux_STRIP=strip
-
--x86_64_linux_CC=gcc -m64
--x86_64_linux_CXX=g++ -m64
-+x86_64_linux_CC=x86_64-linux-gnu-gcc
-+x86_64_linux_CXX=x86_64-linux-gnu-g++
- x86_64_linux_AR=ar
- x86_64_linux_RANLIB=ranlib
- x86_64_linux_NM=nm
-diff --git a/contrib/depends/packages/android_ndk.mk b/contrib/depends/packages/android_ndk.mk
-index 9b8a5332f..5deff76c7 100644
---- a/contrib/depends/packages/android_ndk.mk
-+++ b/contrib/depends/packages/android_ndk.mk
-@@ -7,6 +7,8 @@ $(package)_sha256_hash=5dfbbdc2d3ba859fed90d0e978af87c71a91a5be1f6e1c40ba697503d
- define $(package)_set_vars
- $(package)_config_opts_arm=--arch arm
- $(package)_config_opts_aarch64=--arch arm64
-+$(package)_config_opts_x86_64=--arch x86_64
-+$(package)_config_opts_i686=--arch x86
- endef
-
- define $(package)_extract_cmds
-diff --git a/contrib/depends/packages/packages.mk b/contrib/depends/packages/packages.mk
-index d2d1eca85..8783d4955 100644
---- a/contrib/depends/packages/packages.mk
-+++ b/contrib/depends/packages/packages.mk
-@@ -1,4 +1,4 @@
--packages:=boost openssl zeromq libiconv expat unbound
-+packages:=boost openssl zeromq libiconv expat unbound polyseed
-
- # ccache is useless in gitian builds
- ifneq ($(GITIAN),1)
-diff --git a/contrib/depends/packages/polyseed.mk b/contrib/depends/packages/polyseed.mk
-new file mode 100644
-index 000000000..2ddeac621
---- /dev/null
-+++ b/contrib/depends/packages/polyseed.mk
-@@ -0,0 +1,23 @@
-+package=polyseed
-+$(package)_version=2.0.0
-+$(package)_download_path=https://github.com/tevador/$(package)/archive/refs/tags/
-+$(package)_download_file=v$($(package)_version).tar.gz
-+$(package)_file_name=$(package)-$($(package)_version).tar.gz
-+$(package)_sha256_hash=f36282fcbcd68d32461b8230c89e1a40661bd46b91109681cec637433004135a
-+$(package)_patches=force-static-mingw.patch
-+
-+define $(package)_preprocess_cmds
-+ patch -p1 < $($(package)_patch_dir)/force-static-mingw.patch
-+endef
-+
-+define $(package)_config_cmds
-+ cmake -DCMAKE_INSTALL_PREFIX=$(host_prefix) -DCMAKE_C_COMPILER=$($(package)_cc) .
-+endef
-+
-+define $(package)_build_cmds
-+ $(MAKE)
-+endef
-+
-+define $(package)_stage_cmds
-+ $(MAKE) DESTDIR=$($(package)_staging_dir) install
-+endef
-diff --git a/contrib/depends/packages/sodium.mk b/contrib/depends/packages/sodium.mk
-index 87b34599e..68a5b48ba 100644
---- a/contrib/depends/packages/sodium.mk
-+++ b/contrib/depends/packages/sodium.mk
-@@ -6,7 +6,7 @@ $(package)_sha256_hash=6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e
- $(package)_patches=disable-glibc-getrandom-getentropy.patch fix-whitespace.patch
-
- define $(package)_set_vars
--$(package)_config_opts=--enable-static --disable-shared
-+$(package)_config_opts=--enable-static --disable-shared --with-pic
- $(package)_config_opts+=--prefix=$(host_prefix)
- endef
-
-diff --git a/contrib/depends/patches/polyseed/force-static-mingw.patch b/contrib/depends/patches/polyseed/force-static-mingw.patch
-new file mode 100644
-index 000000000..f05cb2b6a
---- /dev/null
-+++ b/contrib/depends/patches/polyseed/force-static-mingw.patch
-@@ -0,0 +1,23 @@
-+--- a/include/polyseed.h
-++++ b/include/polyseed.h
-+@@ -93,13 +93,13 @@ Shared/static library definitions
-+ - define POLYSEED_STATIC when linking to the static library
-+ */
-+ #if defined(_WIN32) || defined(__CYGWIN__)
-+- #ifdef POLYSEED_SHARED
-+- #define POLYSEED_API __declspec(dllexport)
-+- #elif !defined(POLYSEED_STATIC)
-+- #define POLYSEED_API __declspec(dllimport)
-+- #else
-+- #define POLYSEED_API
-+- #endif
-++// #ifdef POLYSEED_SHARED
-++// #define POLYSEED_API __declspec(dllexport)
-++// #elif !defined(POLYSEED_STATIC)
-++// #define POLYSEED_API __declspec(dllimport)
-++// #else
-++ #define POLYSEED_API
-++// #endif
-+ #define POLYSEED_PRIVATE
-+ #else
-+ #ifdef POLYSEED_SHARED
---
-2.45.2
-
diff --git a/patches/monero/0015-use-proper-error-handling-in-get_seed.patch b/patches/wownero/0006-use-proper-error-handling-in-get_seed.patch
index aef7dcf..8f10b80 100644
--- a/patches/monero/0015-use-proper-error-handling-in-get_seed.patch
+++ b/patches/wownero/0006-use-proper-error-handling-in-get_seed.patch
@@ -1,18 +1,18 @@
-From 6e7a9770e4f18f931f5caca7dec2a197e779afbc Mon Sep 17 00:00:00 2001
+From 776d22d6dc47739074f004979894f3c62d43a0c9 Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Mon, 24 Jun 2024 10:49:12 +0200
-Subject: [PATCH 15/16] use proper error handling in get_seed
+Subject: [PATCH 06/15] use proper error handling in get_seed
---
src/wallet/api/wallet.cpp | 17 ++++++++++++-----
- src/wallet/wallet2.cpp | 3 +++
- 2 files changed, 15 insertions(+), 5 deletions(-)
+ src/wallet/wallet2.cpp | 5 ++++-
+ 2 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index 5ca190c7d..a307d35a7 100644
+index 899ef044a..e16d8f83f 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
-@@ -880,12 +880,19 @@ bool WalletImpl::close(bool store)
+@@ -826,12 +826,19 @@ bool WalletImpl::close(bool store)
std::string WalletImpl::seed(const std::string& seed_offset) const
{
@@ -36,12 +36,12 @@ index 5ca190c7d..a307d35a7 100644
+ }
}
- bool WalletImpl::getPolyseed(std::string &seed_words, std::string &passphrase) const
+ std::string WalletImpl::getSeedLanguage() const
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
-index 7d97e683b..8e44806fc 100644
+index 651161d14..1e527cf97 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
-@@ -1452,11 +1452,13 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab
+@@ -1440,11 +1440,13 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab
bool keys_deterministic = is_deterministic();
if (!keys_deterministic)
{
@@ -55,14 +55,17 @@ index 7d97e683b..8e44806fc 100644
std::cout << "seed_language not set" << std::endl;
return false;
}
-@@ -1466,6 +1468,7 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab
+@@ -1454,8 +1456,9 @@ 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))
{
+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, "Failed to create seed from key for language: "+seed_language+", falling back to English.");
- std::cout << "Failed to create seed from key for language: " << seed_language << ", falling back to English." << std::endl;
- crypto::ElectrumWords::bytes_to_words(key, electrum_words, "English");
+ std::cout << "Failed to create seed from key for language: " << seed_language << std::endl;
+- return false;
++ crypto::ElectrumWords::bytes_to_words(key, electrum_words, "English");
}
+
+ return true;
--
-2.39.2
+2.39.5 (Apple Git-154)
diff --git a/patches/wownero/0007-UR-functions.patch b/patches/wownero/0007-UR-functions.patch
new file mode 100644
index 0000000..ad0592c
--- /dev/null
+++ b/patches/wownero/0007-UR-functions.patch
@@ -0,0 +1,1036 @@
+From 1302c64b0218da6d32b9dd9cbf1c2c56f51e6aff Mon Sep 17 00:00:00 2001
+From: tobtoht <tob@featherwallet.org>
+Date: Tue, 12 Mar 2024 10:09:50 +0100
+Subject: [PATCH 07/15] UR functions
+
+This commit adds UR functions for UR tasks,
+I believe that the right place to get
+UR strings is the wallet code itself,
+especially because it allows us to
+skip the part when we have to store
+things to file to encode them later.
+Now we are fully in memory
+
+Things broken in the commit
+- ledger support.
+ AUTO_LOCK_CMD macro causes compile time
+ issues with this patch. I don't know why
+ just yet, this is a issue that I'll fix
+ later. However (considering the purpose
+ of this patch) it is not a dealbreaker.
+---
+ .gitmodules | 5 +-
+ CMakeLists.txt | 4 +-
+ contrib/depends/hosts/darwin.mk | 2 +-
+ contrib/depends/toolchain.cmake.in | 2 +-
+ external/CMakeLists.txt | 1 +
+ external/bc-ur | 1 +
+ src/device/device_ledger.cpp | 5 +-
+ src/wallet/CMakeLists.txt | 1 +
+ src/wallet/api/pending_transaction.cpp | 33 +++
+ src/wallet/api/pending_transaction.h | 1 +
+ src/wallet/api/unsigned_transaction.cpp | 42 ++++
+ src/wallet/api/unsigned_transaction.h | 1 +
+ src/wallet/api/wallet.cpp | 309 +++++++++++++++++++++++-
+ src/wallet/api/wallet.h | 8 +
+ src/wallet/api/wallet2_api.h | 22 +-
+ src/wallet/wallet2.cpp | 141 +++++++----
+ src/wallet/wallet2.h | 3 +
+ 17 files changed, 521 insertions(+), 60 deletions(-)
+ create mode 160000 external/bc-ur
+
+diff --git a/.gitmodules b/.gitmodules
+index 991071fbe..b24855d9b 100644
+--- a/.gitmodules
++++ b/.gitmodules
+@@ -16,4 +16,7 @@
+ path = external/randomwow
+ url = https://codeberg.org/wownero/RandomWOW
+ branch = 1.2.1-wow
+-
++[submodule "external/bc-ur"]
++ path = external/bc-ur
++ url = https://github.com/MrCyjaneK/bc-ur
++ branch = misc
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index e387ffb1b..8b81c7ab7 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -96,7 +96,8 @@ enable_language(C ASM)
+ set(CMAKE_C_STANDARD 11)
+ set(CMAKE_C_STANDARD_REQUIRED ON)
+ set(CMAKE_C_EXTENSIONS OFF)
+-set(CMAKE_CXX_STANDARD 14)
++set(CMAKE_CXX_STANDARD 17)
++add_definitions(-D_LIBCPP_ENABLE_CXX17_REMOVED_FEATURES) # boost: no template named 'unary_function' in namespace 'std'; did you mean '__unary_function'?
+ set(CMAKE_CXX_STANDARD_REQUIRED ON)
+ set(CMAKE_CXX_EXTENSIONS OFF)
+
+@@ -365,6 +366,7 @@ if(NOT MANUAL_SUBMODULES)
+ endfunction ()
+
+ message(STATUS "Checking submodules")
++ #check_submodule(external/bc-ur)
+ check_submodule(external/miniupnp)
+ check_submodule(external/rapidjson)
+ #check_submodule(external/trezor-common)
+diff --git a/contrib/depends/hosts/darwin.mk b/contrib/depends/hosts/darwin.mk
+index 79d449054..83d83036b 100644
+--- a/contrib/depends/hosts/darwin.mk
++++ b/contrib/depends/hosts/darwin.mk
+@@ -1,4 +1,4 @@
+-OSX_MIN_VERSION=10.8
++OSX_MIN_VERSION=10.14
+ LD64_VERSION=609
+ ifeq (aarch64, $(host_arch))
+ CC_target=arm64-apple-$(host_os)
+diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in
+index f118c754e..f26655d68 100644
+--- a/contrib/depends/toolchain.cmake.in
++++ b/contrib/depends/toolchain.cmake.in
+@@ -94,7 +94,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
+ SET(BREW OFF)
+ SET(PORT OFF)
+ SET(CMAKE_OSX_SYSROOT "@prefix@/native/SDK/")
+- SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.08")
++ SET(CMAKE_OSX_DEPLOYMENT_TARGET "10.14")
+ SET(CMAKE_CXX_STANDARD 14)
+ SET(LLVM_ENABLE_PIC OFF)
+ SET(LLVM_ENABLE_PIE OFF)
+diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
+index 3184ae5a1..88a7bb0b5 100644
+--- a/external/CMakeLists.txt
++++ b/external/CMakeLists.txt
+@@ -72,4 +72,5 @@ endif()
+ add_subdirectory(db_drivers)
+ add_subdirectory(easylogging++)
+ add_subdirectory(qrcodegen)
++add_subdirectory(bc-ur)
+ add_subdirectory(randomwow EXCLUDE_FROM_ALL)
+diff --git a/external/bc-ur b/external/bc-ur
+new file mode 160000
+index 000000000..d82e7c753
+--- /dev/null
++++ b/external/bc-ur
+@@ -0,0 +1 @@
++Subproject commit d82e7c753e710b8000706dc3383b498438795208
+diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
+index 9961d13e7..8403d76e8 100644
+--- a/src/device/device_ledger.cpp
++++ b/src/device/device_ledger.cpp
+@@ -313,12 +313,13 @@ namespace hw {
+
+ /* ======================================================================= */
+ /* LOCKER */
+- /* ======================================================================= */
++ /* ======================================================================= */
+
+ //automatic lock one more level on device ensuring the current thread is allowed to use it
++ #pragma message ("Warning AUTO_LOCK_CMD is intentionally left broken. This is yet to be fixed.")
+ #define AUTO_LOCK_CMD() \
+ /* lock both mutexes without deadlock*/ \
+- boost::lock(device_locker, command_locker); \
++ /* boost::lock(device_locker, command_locker); */ \
+ /* make sure both already-locked mutexes are unlocked at the end of scope */ \
+ boost::lock_guard<boost::recursive_mutex> lock1(device_locker, boost::adopt_lock); \
+ boost::lock_guard<boost::mutex> lock2(command_locker, boost::adopt_lock)
+diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt
+index fdf3f2f5d..66384fe31 100644
+--- a/src/wallet/CMakeLists.txt
++++ b/src/wallet/CMakeLists.txt
+@@ -50,6 +50,7 @@ monero_add_library(wallet
+ target_link_libraries(wallet
+ PUBLIC
+ rpc_base
++ bc-ur
+ multisig
+ common
+ cryptonote_core
+diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp
+index 70a702796..9c3c26ee5 100644
+--- a/src/wallet/api/pending_transaction.cpp
++++ b/src/wallet/api/pending_transaction.cpp
+@@ -42,6 +42,8 @@
+ #include <boost/format.hpp>
+ #include <boost/filesystem.hpp>
+
++#include "bc-ur/src/bc-ur.hpp"
++
+ using namespace std;
+
+ namespace Monero {
+@@ -162,6 +164,37 @@ bool PendingTransactionImpl::commit(const std::string &filename, bool overwrite)
+ return m_status == Status_Ok;
+ }
+
++std::string PendingTransactionImpl::commitUR(int max_fragment_length) {
++
++ LOG_PRINT_L3("m_pending_tx size: " << m_pending_tx.size());
++
++ try {
++ std::string ptx = m_wallet.m_wallet->dump_tx_to_str(m_pending_tx);
++ m_status = Status_Ok;
++ auto urMessage = ur::string_to_bytes(ptx);
++ ur::ByteVector cbor;
++ ur::CborLite::encodeBytes(cbor, urMessage);
++ std::string type;
++ if (m_wallet.watchOnly()) {
++ type = "xmr-txunsigned";
++ } else {
++ type = "xmr-txsigned";
++ }
++ ur::UR urData = ur::UR(type, cbor);
++ auto encoder = ur::UREncoder(urData, max_fragment_length);
++ std::string output;
++ for(size_t i = 0; i < encoder.seq_len(); i++) {
++ output.append("\n"+encoder.next_part());
++ }
++ return output;
++ } catch (const std::exception &e) {
++ m_errorString = string(tr("Unknown exception: ")) + e.what();
++ m_status = Status_Error;
++ return "";
++ }
++}
++
++
+ uint64_t PendingTransactionImpl::amount() const
+ {
+ uint64_t result = 0;
+diff --git a/src/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h
+index 0a9779c07..403bfe281 100644
+--- a/src/wallet/api/pending_transaction.h
++++ b/src/wallet/api/pending_transaction.h
+@@ -46,6 +46,7 @@ public:
+ int status() const override;
+ std::string errorString() const override;
+ bool commit(const std::string &filename = "", bool overwrite = false) override;
++ std::string commitUR(int max_fragment_length = 130) override;
+ uint64_t amount() const override;
+ uint64_t dust() const override;
+ uint64_t fee() const override;
+diff --git a/src/wallet/api/unsigned_transaction.cpp b/src/wallet/api/unsigned_transaction.cpp
+index 6165a2240..fd03e959d 100644
+--- a/src/wallet/api/unsigned_transaction.cpp
++++ b/src/wallet/api/unsigned_transaction.cpp
+@@ -40,6 +40,8 @@
+ #include <sstream>
+ #include <boost/format.hpp>
+
++#include "bc-ur/src/bc-ur.hpp"
++
+ using namespace std;
+
+ namespace Monero {
+@@ -96,6 +98,46 @@ bool UnsignedTransactionImpl::sign(const std::string &signedFileName)
+ return true;
+ }
+
++std::string UnsignedTransactionImpl::signUR(int max_fragment_length)
++{
++ if(m_wallet.watchOnly())
++ {
++ m_errorString = tr("This is a watch only wallet");
++ m_status = Status_Error;
++ return "";
++ }
++ std::vector<tools::wallet2::pending_tx> ptx;
++ try
++ {
++ tools::wallet2::signed_tx_set signed_txes;
++ std::string signedTx = m_wallet.m_wallet->sign_tx_dump_to_str(m_unsigned_tx_set, ptx, signed_txes);
++ if (signedTx.empty())
++ {
++ m_errorString = tr("Failed to sign transaction");
++ m_status = Status_Error;
++ return "";
++ }
++ auto urMessage = ur::string_to_bytes(signedTx);
++ ur::ByteVector cbor;
++ ur::CborLite::encodeBytes(cbor, urMessage);
++ std::string type = "xmr-txsigned";
++ ur::UR urData = ur::UR(type, cbor);
++ auto encoder = ur::UREncoder(urData, max_fragment_length);
++ std::string output;
++ for(size_t i = 0; i < encoder.seq_len(); i++) {
++ output.append("\n"+encoder.next_part());
++ }
++ return output;
++ }
++ catch (const std::exception &e)
++ {
++ m_errorString = string(tr("Failed to sign transaction")) + e.what();
++ m_status = Status_Error;
++ return "";
++ }
++ return "";
++}
++
+ //----------------------------------------------------------------------------------------------------
+ bool UnsignedTransactionImpl::checkLoadedTx(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)
+ {
+diff --git a/src/wallet/api/unsigned_transaction.h b/src/wallet/api/unsigned_transaction.h
+index 30065a7fa..a94b23f75 100644
+--- a/src/wallet/api/unsigned_transaction.h
++++ b/src/wallet/api/unsigned_transaction.h
+@@ -53,6 +53,7 @@ public:
+ uint64_t txCount() const override;
+ // sign txs and save to file
+ bool sign(const std::string &signedFileName) override;
++ std::string signUR(int max_fragment_length = 130) override;
+ std::string confirmationMessage() const override {return m_confirmationMessage;}
+ uint64_t minMixinCount() const override;
+
+diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
+index e16d8f83f..ee000e7ab 100644
+--- a/src/wallet/api/wallet.cpp
++++ b/src/wallet/api/wallet.cpp
+@@ -47,6 +47,7 @@
+
+ #include <boost/locale.hpp>
+ #include <boost/filesystem.hpp>
++#include "bc-ur/src/bc-ur.hpp"
+
+ using namespace std;
+ using namespace cryptonote;
+@@ -1066,6 +1067,24 @@ uint64_t WalletImpl::unlockedBalance(uint32_t accountIndex) const
+ return m_wallet->unlocked_balance(accountIndex, false);
+ }
+
++uint64_t WalletImpl::viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images) const
++{
++ clearStatus();
++
++ std::vector<crypto::key_image> kis;
++ for (const auto &key_image : key_images) {
++ crypto::key_image ki;
++ if (!epee::string_tools::hex_to_pod(key_image, ki))
++ {
++ setStatusError(tr("failed to parse key image"));
++ return 0;
++ }
++ kis.push_back(ki);
++ }
++
++ return m_wallet->view_only_balance(accountIndex, kis);
++}
++
+ uint64_t WalletImpl::blockChainHeight() const
+ {
+ if(m_wallet->light_wallet()) {
+@@ -1208,6 +1227,61 @@ UnsignedTransaction *WalletImpl::loadUnsignedTx(const std::string &unsigned_file
+ return transaction;
+ }
+
++
++UnsignedTransaction *WalletImpl::loadUnsignedTxUR(const std::string &input) {
++ clearStatus();
++ UnsignedTransactionImpl * transaction = new UnsignedTransactionImpl(*this);
++ auto decoder = ur::URDecoder();
++
++ std::string delimiter = "\n";
++ std::string inp = input;
++ size_t pos = 0;
++ std::string token;
++ while ((pos = inp.find(delimiter)) != std::string::npos) {
++ token = inp.substr(0, pos);
++ decoder.receive_part(token);
++ inp.erase(0, pos + delimiter.length());
++ }
++ decoder.receive_part(inp);
++
++ if (decoder.is_failure()) {
++ setStatusError(decoder.result_error().what());
++ transaction->m_status = UnsignedTransaction::Status::Status_Error;
++ transaction->m_errorString = errorString();
++ return transaction;
++ }
++
++ if (!decoder.is_complete()) {
++ setStatusError("file ended but ur didn't complete");
++ transaction->m_status = UnsignedTransaction::Status::Status_Error;
++ transaction->m_errorString = errorString();
++ return transaction;
++ }
++
++ std::string data;
++ auto cbor = decoder.result_ur().cbor();
++ auto i = cbor.begin();
++ auto end = cbor.end();
++ ur::CborLite::decodeBytes(i, end, data);
++
++ if (checkBackgroundSync("cannot load tx") || !m_wallet->parse_unsigned_tx_from_str(data, transaction->m_unsigned_tx_set)){
++ setStatusError(tr("Failed to load unsigned transactions"));
++ transaction->m_status = UnsignedTransaction::Status::Status_Error;
++ transaction->m_errorString = errorString();
++
++ return transaction;
++ }
++
++ // Check tx data and construct confirmation message
++ std::string extra_message;
++ if (!std::get<2>(transaction->m_unsigned_tx_set.transfers).empty())
++ extra_message = (boost::format("%u outputs to import. ") % (unsigned)std::get<2>(transaction->m_unsigned_tx_set.transfers).size()).str();
++ transaction->checkLoadedTx([&transaction](){return transaction->m_unsigned_tx_set.txes.size();}, [&transaction](size_t n)->const tools::wallet2::tx_construction_data&{return transaction->m_unsigned_tx_set.txes[n];}, extra_message);
++ setStatus(transaction->status(), transaction->errorString());
++
++ return transaction;
++}
++
+ bool WalletImpl::submitTransaction(const string &fileName) {
+ clearStatus();
+ if (checkBackgroundSync("cannot submit tx"))
+@@ -1219,7 +1293,7 @@ bool WalletImpl::submitTransaction(const string &fileName) {
+ setStatus(Status_Ok, tr("Failed to load transaction from file"));
+ return false;
+ }
+-
++
+ if(!transaction->commit()) {
+ setStatusError(transaction->m_errorString);
+ return false;
+@@ -1228,6 +1302,61 @@ bool WalletImpl::submitTransaction(const string &fileName) {
+ return true;
+ }
+
++
++bool WalletImpl::submitTransactionUR(const string &input) {
++ clearStatus();
++ auto decoder = ur::URDecoder();
++
++ std::string delimiter = "\n";
++ std::string inp = input;
++ size_t pos = 0;
++ std::string token;
++ while ((pos = inp.find(delimiter)) != std::string::npos) {
++ token = inp.substr(0, pos);
++ decoder.receive_part(token);
++ inp.erase(0, pos + delimiter.length());
++ }
++ decoder.receive_part(inp);
++
++ if (decoder.is_failure()) {
++ setStatusError(decoder.result_error().what());
++ return false;
++ }
++
++ if (!decoder.is_complete()) {
++ setStatusError("file ended but ur didn't complete");
++ return false;
++ }
++
++ std::string data;
++ auto cbor = decoder.result_ur().cbor();
++ auto i = cbor.begin();
++ auto end = cbor.end();
++ ur::CborLite::decodeBytes(i, end, data);
++ if (checkBackgroundSync("cannot submit tx"))
++ return false;
++ std::unique_ptr<PendingTransactionImpl> transaction(new PendingTransactionImpl(*this));
++
++ bool r = m_wallet->parse_tx_from_str(data, transaction->m_pending_tx, NULL);
++ if (!r) {
++ setStatus(Status_Ok, tr("Failed to load transaction from file"));
++ return false;
++ }
++
++ if(!transaction->commit()) {
++ setStatusError(transaction->m_errorString);
++ return false;
++ }
++
++ return true;
++}
++
++
++bool WalletImpl::hasUnknownKeyImages() const
++{
++ return m_wallet->has_unknown_key_images();
++}
++
+ bool WalletImpl::exportKeyImages(const string &filename, bool all)
+ {
+ if (m_wallet->watch_only())
+@@ -1255,6 +1384,39 @@ bool WalletImpl::exportKeyImages(const string &filename, bool all)
+ return true;
+ }
+
++std::string WalletImpl::exportKeyImagesUR(size_t max_fragment_length, bool all)
++{
++ if (m_wallet->watch_only())
++ {
++ setStatusError(tr("Wallet is view only"));
++ return "";
++ }
++ if (checkBackgroundSync("cannot export key images"))
++ return "";
++
++ try
++ {
++ std::string keyImages = m_wallet->export_key_images_str(all);
++ auto urMessage = ur::string_to_bytes(keyImages);
++ ur::ByteVector cbor;
++ ur::CborLite::encodeBytes(cbor, urMessage);
++ ur::UR urData = ur::UR("xmr-keyimage", cbor);
++ auto encoder = ur::UREncoder(urData, max_fragment_length);
++ std::string output;
++ for(size_t i = 0; i < encoder.seq_len(); i++) {
++ output.append("\n"+encoder.next_part());
++ }
++ return output;
++ }
++ catch (const std::exception &e)
++ {
++ LOG_ERROR("Error exporting key images: " << e.what());
++ setStatusError(e.what());
++ return "";
++ }
++ return "";
++}
++
+ bool WalletImpl::importKeyImages(const string &filename)
+ {
+ if (checkBackgroundSync("cannot import key images"))
+@@ -1280,6 +1442,62 @@ bool WalletImpl::importKeyImages(const string &filename)
+ return true;
+ }
+
++
++bool WalletImpl::importKeyImagesUR(const string &input)
++{
++ if (checkBackgroundSync("cannot import key images"))
++ return false;
++ if (!trustedDaemon()) {
++ setStatusError(tr("Key images can only be imported with a trusted daemon"));
++ return false;
++ }
++ try
++ {
++ auto decoder = ur::URDecoder();
++ std::string delimiter = "\n";
++ std::string inp = input;
++ size_t pos = 0;
++ std::string token;
++ while ((pos = inp.find(delimiter)) != std::string::npos) {
++ token = inp.substr(0, pos);
++ decoder.receive_part(token);
++ inp.erase(0, pos + delimiter.length());
++ }
++ decoder.receive_part(inp);
++
++ if (decoder.is_failure()) {
++ setStatusError(decoder.result_error().what());
++ return false;
++ }
++
++ if (!decoder.is_complete()) {
++ setStatusError("file ended but ur didn't complete");
++ return false;
++ }
++
++ std::string data;
++ auto cbor = decoder.result_ur().cbor();
++ auto i = cbor.begin();
++ auto end = cbor.end();
++ ur::CborLite::decodeBytes(i, end, data);
++
++ uint64_t spent = 0, unspent = 0;
++
++ uint64_t height = m_wallet->import_key_images_str(data, spent, unspent);
++ LOG_PRINT_L2("Signed key images imported to height " << height << ", "
++ << print_money(spent) << " spent, " << print_money(unspent) << " unspent");
++ }
++ catch (const std::exception &e)
++ {
++ LOG_ERROR("Error exporting key images: " << e.what());
++ setStatusError(string(tr("Failed to import key images: ")) + e.what());
++ return false;
++ }
++
++ return true;
++}
++
++
+ bool WalletImpl::exportOutputs(const string &filename, bool all)
+ {
+ if (checkBackgroundSync("cannot export outputs"))
+@@ -1312,6 +1530,40 @@ bool WalletImpl::exportOutputs(const string &filename, bool all)
+ return true;
+ }
+
++std::string WalletImpl::exportOutputsUR(size_t max_fragment_length, bool all)
++{
++
++ if (checkBackgroundSync("cannot export outputs"))
++ return "";
++ if (m_wallet->key_on_device())
++ {
++ setStatusError(string(tr("Not supported on HW wallets.")));
++ return "";
++ }
++
++ try
++ {
++ std::string data = m_wallet->export_outputs_to_str(all);
++ auto urMessage = ur::string_to_bytes(data);
++ ur::ByteVector cbor;
++ ur::CborLite::encodeBytes(cbor, urMessage);
++ ur::UR urData = ur::UR("xmr-output", cbor);
++ auto encoder = ur::UREncoder(urData, max_fragment_length);
++ std::string output;
++ for(size_t i = 0; i < encoder.seq_len(); i++) {
++ output.append("\n"+encoder.next_part());
++ }
++ return output;
++ }
++ catch (const std::exception &e)
++ {
++ LOG_ERROR("Error exporting outputs: " << e.what());
++ setStatusError(string(tr("Error exporting outputs: ")) + e.what());
++ return "";
++ }
++}
++
++
+ bool WalletImpl::importOutputs(const string &filename)
+ {
+ if (checkBackgroundSync("cannot import outputs"))
+@@ -1346,6 +1598,61 @@ bool WalletImpl::importOutputs(const string &filename)
+ return true;
+ }
+
++
++bool WalletImpl::importOutputsUR(const string &input)
++{
++ if (checkBackgroundSync("cannot import outputs"))
++ return false;
++ if (m_wallet->key_on_device())
++ {
++ setStatusError(string(tr("Not supported on HW wallets.")));
++ return false;
++ }
++
++ try
++ {
++ auto decoder = ur::URDecoder();
++
++ std::string delimiter = "\n";
++ std::string inp = input;
++ size_t pos = 0;
++ std::string token;
++ while ((pos = inp.find(delimiter)) != std::string::npos) {
++ token = inp.substr(0, pos);
++ decoder.receive_part(token);
++ inp.erase(0, pos + delimiter.length());
++ }
++ decoder.receive_part(inp);
++
++ if (decoder.is_failure()) {
++ setStatusError(decoder.result_error().what());
++ return false;
++ }
++
++ if (!decoder.is_complete()) {
++ setStatusError("file ended but ur didn't complete");
++ return false;
++ }
++
++ std::string data;
++ auto cbor = decoder.result_ur().cbor();
++ auto i = cbor.begin();
++ auto end = cbor.end();
++ ur::CborLite::decodeBytes(i, end, data);
++ size_t n_outputs = m_wallet->import_outputs_from_str(std::string(data));
++ LOG_PRINT_L2(std::to_string(n_outputs) << " outputs imported");
++ }
++ catch (const std::exception &e)
++ {
++ LOG_ERROR("Failed to import outputs: " << e.what());
++ setStatusError(string(tr("Failed to import outputs: ")) + e.what());
++ return false;
++ }
++
++ return true;
++}
++
++
+ bool WalletImpl::scanTransactions(const std::vector<std::string> &txids)
+ {
+ if (checkBackgroundSync("cannot scan transactions"))
+diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
+index ac7ce2f6a..edf8bb8ce 100644
+--- a/src/wallet/api/wallet.h
++++ b/src/wallet/api/wallet.h
+@@ -112,6 +112,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;
++ uint64_t viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images) const override;
+ uint64_t blockChainHeight() const override;
+ uint64_t approximateBlockChainHeight() const override;
+ uint64_t estimateBlockChainHeight() const override;
+@@ -164,11 +165,18 @@ public:
+ std::set<uint32_t> subaddr_indices = {}) override;
+ virtual PendingTransaction * createSweepUnmixableTransaction() override;
+ bool submitTransaction(const std::string &fileName) override;
++ bool submitTransactionUR(const std::string &input) override;
+ virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override;
++ virtual UnsignedTransaction * loadUnsignedTxUR(const std::string &input) override;
++ bool hasUnknownKeyImages() const override;
+ bool exportKeyImages(const std::string &filename, bool all = false) override;
++ std::string exportKeyImagesUR(size_t max_fragment_length, bool all = false) override;
+ bool importKeyImages(const std::string &filename) override;
++ bool importKeyImagesUR(const std::string &input) override;
+ bool exportOutputs(const std::string &filename, bool all = false) override;
++ std::string exportOutputsUR(size_t max_fragment_length, bool all) override;
+ bool importOutputs(const std::string &filename) override;
++ bool importOutputsUR(const std::string &filename) override;
+ bool scanTransactions(const std::vector<std::string> &txids) override;
+
+ bool setupBackgroundSync(const BackgroundSyncType background_sync_type, const std::string &wallet_password, const optional<std::string> &background_cache_password = optional<std::string>()) override;
+diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
+index e349df176..764adbfbf 100644
+--- a/src/wallet/api/wallet2_api.h
++++ b/src/wallet/api/wallet2_api.h
+@@ -91,6 +91,7 @@ struct PendingTransaction
+ virtual std::string errorString() const = 0;
+ // commit transaction or save to file if filename is provided.
+ virtual bool commit(const std::string &filename = "", bool overwrite = false) = 0;
++ virtual std::string commitUR(int max_fragment_length = 130) = 0;
+ virtual uint64_t amount() const = 0;
+ virtual uint64_t dust() const = 0;
+ virtual uint64_t fee() const = 0;
+@@ -160,7 +161,8 @@ struct UnsignedTransaction
+ * @param signedFileName
+ * return - true on success
+ */
+- virtual bool sign(const std::string &signedFileName) = 0;
++ virtual bool sign(const std::string &signedFileName) = 0;
++ virtual std::string signUR(int max_fragment_length = 130) = 0;
+ };
+
+ /**
+@@ -626,6 +628,7 @@ struct Wallet
+ result += unlockedBalance(i);
+ return result;
+ }
++ virtual uint64_t viewOnlyBalance(uint32_t accountIndex, const std::vector<std::string> &key_images = {}) const = 0;
+
+ /**
+ * @brief watchOnly - checks if wallet is watch only
+@@ -884,13 +887,15 @@ struct Wallet
+ * after object returned
+ */
+ virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) = 0;
+-
+- /*!
++ virtual UnsignedTransaction * loadUnsignedTxUR(const std::string &input) = 0;
++
++ /*!
+ * \brief submitTransaction - submits transaction in signed tx file
+ * \return - true on success
+ */
+ virtual bool submitTransaction(const std::string &fileName) = 0;
+-
++ virtual bool submitTransactionUR(const std::string &input) = 0;
++
+
+ /*!
+ * \brief disposeTransaction - destroys transaction object
+@@ -906,6 +911,8 @@ struct Wallet
+ virtual uint64_t estimateTransactionFee(const std::vector<std::pair<std::string, uint64_t>> &destinations,
+ PendingTransaction::Priority priority) const = 0;
+
++ virtual bool hasUnknownKeyImages() const = 0;
++
+ /*!
+ * \brief exportKeyImages - exports key images to file
+ * \param filename
+@@ -913,20 +920,22 @@ struct Wallet
+ * \return - true on success
+ */
+ virtual bool exportKeyImages(const std::string &filename, bool all = false) = 0;
+-
++ virtual std::string exportKeyImagesUR(size_t max_fragment_length, bool all = false) = 0;
+ /*!
+ * \brief importKeyImages - imports key images from file
+ * \param filename
+ * \return - true on success
+ */
+ virtual bool importKeyImages(const std::string &filename) = 0;
++ virtual bool importKeyImagesUR(const std::string &input) = 0;
+
+ /*!
+- * \brief importOutputs - exports outputs to file
++ * \brief exportOutputs - exports outputs to file
+ * \param filename
+ * \return - true on success
+ */
+ virtual bool exportOutputs(const std::string &filename, bool all = false) = 0;
++ virtual std::string exportOutputsUR(size_t max_fragment_length, bool all = false) = 0;
+
+ /*!
+ * \brief importOutputs - imports outputs from file
+@@ -934,6 +943,7 @@ struct Wallet
+ * \return - true on success
+ */
+ virtual bool importOutputs(const std::string &filename) = 0;
++ virtual bool importOutputsUR(const std::string &filename) = 0;
+
+ /*!
+ * \brief scanTransactions - scan a list of transaction ids, this operation may reveal the txids to the remote node and affect your privacy
+diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
+index 1e527cf97..671fa5298 100644
+--- a/src/wallet/wallet2.cpp
++++ b/src/wallet/wallet2.cpp
+@@ -948,6 +948,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);
+@@ -6989,6 +6999,25 @@ uint64_t wallet2::unlocked_balance(uint32_t index_major, bool strict, uint64_t *
+ return amount;
+ }
+ //----------------------------------------------------------------------------------------------------
++uint64_t wallet2::view_only_balance(uint32_t index_major, const std::vector<crypto::key_image>& selected_inputs)
++{
++ uint64_t amount = 0;
++ for (const auto &td : m_transfers) {
++ if (is_preferred_input(selected_inputs, td.m_key_image) &&
++ !is_spent(td, false) &&
++ !td.m_frozen &&
++ !td.m_key_image_partial &&
++ td.m_key_image_known &&
++ td.is_rct() &&
++ is_transfer_unlocked(td) &&
++ td.m_subaddr_index.major == index_major)
++ {
++ amount += td.m_amount;
++ }
++ }
++ return amount;
++}
++//----------------------------------------------------------------------------------------------------
+ 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;
+@@ -7840,9 +7869,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;
+
+- // compute public keys from out secret keys
+- crypto::public_key tx_pub_key;
+- crypto::secret_key_to_public_key(txs[n].tx_key, tx_pub_key);
++ crypto::public_key tx_pub_key = get_tx_pub_key_from_extra(tx);
+ std::vector<crypto::public_key> additional_tx_pub_keys;
+ for (const crypto::secret_key &skey: txs[n].additional_tx_keys)
+ {
+@@ -11232,7 +11259,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;
+ }
+- if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && (use_rct ? true : !td.is_rct()) && is_transfer_unlocked(td) && td.m_subaddr_index.major == subaddr_account && subaddr_indices.count(td.m_subaddr_index.minor) == 1)
++ if (!is_spent(td, false) && !td.m_frozen && !td.m_key_image_partial && td.m_key_image_known && (use_rct ? true : !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)
+ {
+@@ -11282,9 +11309,15 @@ 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");
+
+- if (unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty())
+- return std::vector<wallet2::pending_tx>();
++ // use tobotoht's code path on view-only wallet, otherwise default to upstream
++ bool throwOnNoEnotes = m_account.get_device().device_protocol() == hw::device::PROTOCOL_COLD || m_watch_only || m_multisig || m_is_background_wallet;
+
++ if (throwOnNoEnotes) {
++ THROW_WALLET_EXCEPTION_IF(unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty(), error::wallet_internal_error, "No enotes available to spend")
++ } else {
++ if (unused_dust_indices_per_subaddr.empty() && unused_transfers_indices_per_subaddr.empty())
++ return std::vector<wallet2::pending_tx>();
++ }
+ // if empty, put dummy entry so that the front can be referenced later in the loop
+ if (unused_dust_indices_per_subaddr.empty())
+ unused_dust_indices_per_subaddr.push_back({});
+@@ -13911,33 +13944,40 @@ crypto::public_key wallet2::get_tx_pub_key_from_received_outs(const tools::walle
+
+ bool wallet2::export_key_images(const std::string &filename, bool all) const
+ {
+- PERF_TIMER(export_key_images);
+- std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all);
+- std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC));
+- const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
+- const uint32_t offset = ski.first;
++ std::string data = export_key_images_str(all);
++ return save_to_file(filename, data);
++}
+
+- std::string data;
+- data.reserve(4 + ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)) + 2 * sizeof(crypto::public_key));
+- data.resize(4);
+- data[0] = offset & 0xff;
+- data[1] = (offset >> 8) & 0xff;
+- data[2] = (offset >> 16) & 0xff;
+- data[3] = (offset >> 24) & 0xff;
+- data += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key));
+- data += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key));
+- for (const auto &i: ski.second)
+- {
+- data += std::string((const char *)&i.first, sizeof(crypto::key_image));
+- data += std::string((const char *)&i.second, sizeof(crypto::signature));
+- }
++std::string wallet2::export_key_images_str(bool all) const
++{
++ PERF_TIMER(export_key_images);
++ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> ski = export_key_images(all);
++ std::string magic(KEY_IMAGE_EXPORT_FILE_MAGIC, strlen(KEY_IMAGE_EXPORT_FILE_MAGIC));
++ const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
++ const uint32_t offset = ski.first;
+
+- // encrypt data, keep magic plaintext
+- PERF_TIMER(export_key_images_encrypt);
+- std::string ciphertext = encrypt_with_view_secret_key(data);
+- return save_to_file(filename, magic + ciphertext);
++ std::string data;
++ data.reserve(4 + ski.second.size() * (sizeof(crypto::key_image) + sizeof(crypto::signature)) + 2 * sizeof(crypto::public_key));
++ data.resize(4);
++ data[0] = offset & 0xff;
++ data[1] = (offset >> 8) & 0xff;
++ data[2] = (offset >> 16) & 0xff;
++ data[3] = (offset >> 24) & 0xff;
++ data += std::string((const char *)&keys.m_spend_public_key, sizeof(crypto::public_key));
++ data += std::string((const char *)&keys.m_view_public_key, sizeof(crypto::public_key));
++ for (const auto &i: ski.second)
++ {
++ data += std::string((const char *)&i.first, sizeof(crypto::key_image));
++ data += std::string((const char *)&i.second, sizeof(crypto::signature));
++ }
++
++ // encrypt data, keep magic plaintext
++ PERF_TIMER(export_key_images_encrypt);
++ std::string ciphertext = encrypt_with_view_secret_key(data);
++ return magic + ciphertext;
+ }
+
++
+ //----------------------------------------------------------------------------------------------------
+ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> wallet2::export_key_images(bool all) const
+ {
+@@ -13992,53 +14032,60 @@ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>
+ return std::make_pair(offset, ski);
+ }
+
+-uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent)
++uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent) {
++ std::string data;
++
++ bool r = load_from_file(filename, data);
++
++ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, std::string(tr("failed to read file ")) + filename);
++
++ return import_key_images_str(data, spent, unspent);
++}
++
++uint64_t wallet2::import_key_images_str(const std::string &data, uint64_t &spent, uint64_t &unspent)
+ {
+ PERF_TIMER(import_key_images_fsu);
+- std::string data;
+- bool r = load_from_file(filename, data);
+-
+- THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, std::string(tr("failed to read file ")) + filename);
++ std::string data_local = data;
+
+ const size_t magiclen = strlen(KEY_IMAGE_EXPORT_FILE_MAGIC);
+ if (data.size() < magiclen || memcmp(data.data(), KEY_IMAGE_EXPORT_FILE_MAGIC, magiclen))
+ {
+- THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Bad key image export file magic in ") + filename);
++ THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Bad key image export file magic"));
+ }
+
+ try
+ {
+ PERF_TIMER(import_key_images_decrypt);
+- data = decrypt_with_view_secret_key(std::string(data, magiclen));
++ data_local = decrypt_with_view_secret_key(std::string(data, magiclen));
+ }
+ catch (const std::exception &e)
+ {
+- THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to decrypt ") + filename + ": " + e.what());
++ THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to decrypt ") + ": " + e.what());
+ }
+
+ const size_t headerlen = 4 + 2 * sizeof(crypto::public_key);
+- THROW_WALLET_EXCEPTION_IF(data.size() < headerlen, error::wallet_internal_error, std::string("Bad data size from file ") + filename);
+- const uint32_t offset = (uint8_t)data[0] | (((uint8_t)data[1]) << 8) | (((uint8_t)data[2]) << 16) | (((uint8_t)data[3]) << 24);
+- const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[4];
+- const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[4 + sizeof(crypto::public_key)];
++ THROW_WALLET_EXCEPTION_IF(data_local.size() < headerlen, error::wallet_internal_error, std::string("Bad data size from file "));
++ const uint32_t offset = (uint8_t)data_local[0] | (((uint8_t)data_local[1]) << 8) | (((uint8_t)data_local[2]) << 16) | (((uint8_t)data_local[3]) << 24);
++ const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data_local[4];
++ const crypto::public_key &public_view_key = *(const crypto::public_key*)&data_local[4 + sizeof(crypto::public_key)];
+ const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
+ if (public_spend_key != keys.m_spend_public_key || public_view_key != keys.m_view_public_key)
+ {
+- THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string( "Key images from ") + filename + " are for a different account");
++ THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string( "Key images from ") + " are for a different account");
+ }
+ THROW_WALLET_EXCEPTION_IF(offset > m_transfers.size(), error::wallet_internal_error, "Offset larger than known outputs");
+
+ const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature);
+- THROW_WALLET_EXCEPTION_IF((data.size() - headerlen) % record_size,
+- error::wallet_internal_error, std::string("Bad data size from file ") + filename);
+- size_t nki = (data.size() - headerlen) / record_size;
++ THROW_WALLET_EXCEPTION_IF((data_local.size() - headerlen) % record_size,
++ error::wallet_internal_error, std::string("Bad data size from file "));
++ size_t nki = (data_local.size() - headerlen) / record_size;
+
+ std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
+ ski.reserve(nki);
+ for (size_t n = 0; n < nki; ++n)
+ {
+- crypto::key_image key_image = *reinterpret_cast<const crypto::key_image*>(&data[headerlen + n * record_size]);
+- crypto::signature signature = *reinterpret_cast<const crypto::signature*>(&data[headerlen + n * record_size + sizeof(crypto::key_image)]);
++ crypto::key_image key_image = *reinterpret_cast<const crypto::key_image*>(&data_local[headerlen + n * record_size]);
++ crypto::signature signature = *reinterpret_cast<const crypto::signature*>(&data_local[headerlen + n * record_size + sizeof(crypto::key_image)]);
+
+ ski.push_back(std::make_pair(key_image, signature));
+ }
+diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
+index c07a47c11..80ff0698d 100644
+--- a/src/wallet/wallet2.h
++++ b/src/wallet/wallet2.h
+@@ -1150,6 +1150,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);
++ uint64_t view_only_balance(uint32_t index_major, const std::vector<crypto::key_image>& selected_inputs = {});
+ // 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);
+@@ -1624,9 +1625,11 @@ private:
+ std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> export_blockchain() const;
+ void import_blockchain(const std::tuple<size_t, crypto::hash, std::vector<crypto::hash>> &bc);
+ bool export_key_images(const std::string &filename, bool all = false) const;
++ std::string export_key_images_str(bool all) const;
+ std::pair<uint64_t, std::vector<std::pair<crypto::key_image, crypto::signature>>> export_key_images(bool all = false) const;
+ uint64_t import_key_images(const std::vector<std::pair<crypto::key_image, crypto::signature>> &signed_key_images, size_t offset, uint64_t &spent, uint64_t &unspent, bool check_spent = true);
+ uint64_t import_key_images(const std::string &filename, uint64_t &spent, uint64_t &unspent);
++ uint64_t import_key_images_str(const std::string &data, uint64_t &spent, uint64_t &unspent);
+ bool import_key_images(std::vector<crypto::key_image> key_images, size_t offset=0, boost::optional<std::unordered_set<size_t>> selected_transfers=boost::none);
+ bool import_key_images(signed_tx_set & signed_tx, size_t offset=0, bool only_selected_transfers=false);
+ crypto::public_key get_tx_pub_key_from_received_outs(const tools::wallet2::transfer_details &td) const;
+--
+2.39.5 (Apple Git-154)
+
diff --git a/patches/wownero/0007-macos-build-fix.patch b/patches/wownero/0007-macos-build-fix.patch
deleted file mode 100644
index 2077208..0000000
--- a/patches/wownero/0007-macos-build-fix.patch
+++ /dev/null
@@ -1,114 +0,0 @@
-From b3916ec820e9b1aa3ad5af732c3fd32591b21a05 Mon Sep 17 00:00:00 2001
-From: Your Name <you@example.com>
-Date: Thu, 28 Mar 2024 02:03:08 +0100
-Subject: [PATCH 07/14] macos build fix
-
----
- contrib/depends/hosts/darwin.mk | 2 +
- contrib/depends/packages/polyseed.mk | 13 +++--
- .../polyseed/0001-disable-soname.patch | 48 +++++++++++++++++++
- 3 files changed, 59 insertions(+), 4 deletions(-)
- create mode 100644 contrib/depends/patches/polyseed/0001-disable-soname.patch
-
-diff --git a/contrib/depends/hosts/darwin.mk b/contrib/depends/hosts/darwin.mk
-index 79d449054..cbe795081 100644
---- a/contrib/depends/hosts/darwin.mk
-+++ b/contrib/depends/hosts/darwin.mk
-@@ -8,6 +8,8 @@ endif
- darwin_CC=clang -target $(CC_target) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(host_prefix)/native/SDK/ -mlinker-version=$(LD64_VERSION) -B$(host_prefix)/native/bin/$(host)-
- darwin_CXX=clang++ -target $(CC_target) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(host_prefix)/native/SDK/ -mlinker-version=$(LD64_VERSION) -stdlib=libc++ -B$(host_prefix)/native/bin/$(host)-
-
-+darwin_RANLIB=$(host_prefix)/native/bin/$(host)-ranlib
-+
- darwin_CFLAGS=-pipe
- darwin_CXXFLAGS=$(darwin_CFLAGS)
- darwin_ARFLAGS=cr
-diff --git a/contrib/depends/packages/polyseed.mk b/contrib/depends/packages/polyseed.mk
-index 2ddeac621..0071b20f3 100644
---- a/contrib/depends/packages/polyseed.mk
-+++ b/contrib/depends/packages/polyseed.mk
-@@ -4,18 +4,23 @@ $(package)_download_path=https://github.com/tevador/$(package)/archive/refs/tags
- $(package)_download_file=v$($(package)_version).tar.gz
- $(package)_file_name=$(package)-$($(package)_version).tar.gz
- $(package)_sha256_hash=f36282fcbcd68d32461b8230c89e1a40661bd46b91109681cec637433004135a
--$(package)_patches=force-static-mingw.patch
-+$(package)_patches=force-static-mingw.patch 0001-disable-soname.patch
-
- define $(package)_preprocess_cmds
-- patch -p1 < $($(package)_patch_dir)/force-static-mingw.patch
-+ patch -p1 < $($(package)_patch_dir)/force-static-mingw.patch &&\
-+ patch -p1 < $($(package)_patch_dir)/0001-disable-soname.patch
- endef
-
- define $(package)_config_cmds
-- cmake -DCMAKE_INSTALL_PREFIX=$(host_prefix) -DCMAKE_C_COMPILER=$($(package)_cc) .
-+ CC="$($(package)_cc)" cmake -DCMAKE_INSTALL_PREFIX="$(host_prefix)" .
-+endef
-+
-+define $(package)_set_vars
-+ $(package)_build_opts=CC="$($(package)_cc)"
- endef
-
- define $(package)_build_cmds
-- $(MAKE)
-+ CC="$($(package)_cc)" $(MAKE)
- endef
-
- define $(package)_stage_cmds
-diff --git a/contrib/depends/patches/polyseed/0001-disable-soname.patch b/contrib/depends/patches/polyseed/0001-disable-soname.patch
-new file mode 100644
-index 000000000..bd97dd394
---- /dev/null
-+++ b/contrib/depends/patches/polyseed/0001-disable-soname.patch
-@@ -0,0 +1,48 @@
-+From aabafcfc0572651436d024a635483c49042fad7f Mon Sep 17 00:00:00 2001
-+From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-+Date: Thu, 28 Mar 2024 00:32:51 +0100
-+Subject: [PATCH] disable soname
-+
-+---
-+ CMakeLists.txt | 16 +++++++++-------
-+ 1 file changed, 9 insertions(+), 7 deletions(-)
-+
-+diff --git a/CMakeLists.txt b/CMakeLists.txt
-+index 8a8e7c2..5301353 100644
-+--- a/CMakeLists.txt
-++++ b/CMakeLists.txt
-+@@ -36,6 +36,7 @@ include_directories(polyseed
-+ target_compile_definitions(polyseed PRIVATE POLYSEED_SHARED)
-+ set_target_properties(polyseed PROPERTIES VERSION 2.0.0
-+ SOVERSION 2
-++ NO_SONAME 1
-+ C_STANDARD 11
-+ C_STANDARD_REQUIRED ON)
-+
-+@@ -45,16 +46,17 @@ include_directories(polyseed_static
-+ include/)
-+ target_compile_definitions(polyseed_static PRIVATE POLYSEED_STATIC)
-+ set_target_properties(polyseed_static PROPERTIES OUTPUT_NAME polyseed
-++ NO_SONAME 1
-+ C_STANDARD 11
-+ C_STANDARD_REQUIRED ON)
-+
-+-add_executable(polyseed-tests
-+- tests/tests.c)
-+-include_directories(polyseed-tests
-+- include/)
-+-target_compile_definitions(polyseed-tests PRIVATE POLYSEED_STATIC)
-+-target_link_libraries(polyseed-tests
-+- PRIVATE polyseed_static)
-++# add_executable(polyseed-tests
-++# tests/tests.c)
-++# include_directories(polyseed-tests
-++# include/)
-++# target_compile_definitions(polyseed-tests PRIVATE POLYSEED_STATIC)
-++# target_link_libraries(polyseed-tests
-++# PRIVATE polyseed_static)
-+
-+ include(GNUInstallDirs)
-+ install(TARGETS polyseed polyseed_static
-+--
-+2.39.2
---
-2.45.2
-
diff --git a/patches/wownero/0008-FIX-wallet-listener-crashing.patch b/patches/wownero/0008-FIX-wallet-listener-crashing.patch
deleted file mode 100644
index b935770..0000000
--- a/patches/wownero/0008-FIX-wallet-listener-crashing.patch
+++ /dev/null
@@ -1,58 +0,0 @@
-From 80c2ee2b596b77d445c5e84f646a22949736fbd4 Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Tue, 2 Apr 2024 11:56:09 +0200
-Subject: [PATCH 08/14] 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 ed309de34..ee0eeeb01 100644
---- a/src/wallet/api/wallet.cpp
-+++ b/src/wallet/api/wallet.cpp
-@@ -201,8 +201,11 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
- << ", burnt: " << print_money(burnt)
- << ", raw_output_value: " << print_money(amount)
- << ", idx: " << subaddr_index);
-- m_listener->moneyReceived(tx_hash, amount);
-- m_listener->updated();
-+ // do not signal on sent tx if wallet is not syncronized completely
-+ if (m_listener && m_wallet->synchronized()) {
-+ m_listener->moneyReceived(tx_hash, amount);
-+ m_listener->updated();
-+ }
- }
-
- virtual void on_unconfirmed_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index)
-@@ -214,8 +217,11 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
- << ", tx: " << tx_hash
- << ", amount: " << print_money(amount)
- << ", idx: " << subaddr_index);
-- m_listener->unconfirmedMoneyReceived(tx_hash, amount);
-- m_listener->updated();
-+ // do not signal on sent tx if wallet is not syncronized completely
-+ if (m_listener && m_wallet->synchronized()) {
-+ m_listener->unconfirmedMoneyReceived(tx_hash, amount);
-+ m_listener->updated();
-+ }
- }
-
- virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx,
-@@ -227,8 +233,11 @@ struct Wallet2CallbackImpl : public tools::i_wallet2_callback
- << ", tx: " << tx_hash
- << ", amount: " << print_money(amount)
- << ", idx: " << subaddr_index);
-- m_listener->moneySpent(tx_hash, amount);
-- m_listener->updated();
-+ // do not signal on sent tx if wallet is not syncronized completely
-+ if (m_listener && m_wallet->synchronized()) {
-+ m_listener->moneySpent(tx_hash, amount);
-+ m_listener->updated();
-+ }
- }
-
- virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx)
---
-2.45.2
-
diff --git a/patches/monero/0016-add-dummy-device-for-ledger.patch b/patches/wownero/0008-add-dummy-device-for-ledger.patch
index dddb4b1..6d40bb2 100644
--- a/patches/monero/0016-add-dummy-device-for-ledger.patch
+++ b/patches/wownero/0008-add-dummy-device-for-ledger.patch
@@ -1,29 +1,30 @@
-From 77f328ba6befb9b964f764a27f8a03b71bf9095d Mon Sep 17 00:00:00 2001
+From 07a3019d94feb48f746dbc780db1e4d2e0d6080c Mon Sep 17 00:00:00 2001
From: Czarek Nakamoto <cyjan@mrcyjanek.net>
Date: Wed, 26 Jun 2024 15:04:38 +0200
-Subject: [PATCH 16/16] add dummy device for ledger
+Subject: [PATCH 08/15] add dummy device for ledger
---
- CMakeLists.txt | 6 +-
- src/device/CMakeLists.txt | 6 +-
- src/device/device.cpp | 10 ++-
- src/device/device.hpp | 12 +--
- src/device/device_io_dummy.cpp | 133 +++++++++++++++++++++++++++++++++
- src/device/device_io_dummy.hpp | 74 ++++++++++++++++++
- src/device/device_ledger.cpp | 6 +-
- src/device/device_ledger.hpp | 7 +-
- src/wallet/api/wallet.cpp | 94 +++++++++++++++++++++++
- src/wallet/api/wallet.h | 18 +++++
- src/wallet/api/wallet2_api.h | 12 +++
- 11 files changed, 357 insertions(+), 21 deletions(-)
+ CMakeLists.txt | 6 +-
+ src/device/CMakeLists.txt | 6 +-
+ src/device/device.cpp | 10 ++-
+ src/device/device.hpp | 12 +--
+ src/device/device_io_dummy.cpp | 133 ++++++++++++++++++++++++++++++
+ src/device/device_io_dummy.hpp | 74 +++++++++++++++++
+ src/device/device_ledger.cpp | 6 +-
+ src/device/device_ledger.hpp | 7 +-
+ src/wallet/api/wallet.cpp | 94 +++++++++++++++++++++
+ src/wallet/api/wallet.h | 18 ++++
+ src/wallet/api/wallet2_api.h | 12 +++
+ src/wallet/api/wallet_manager.cpp | 12 ++-
+ 12 files changed, 365 insertions(+), 25 deletions(-)
create mode 100644 src/device/device_io_dummy.cpp
create mode 100644 src/device/device_io_dummy.hpp
diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 6028c0961..e7fa90abb 100644
+index 8b81c7ab7..abe44eca5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
-@@ -694,8 +694,12 @@ include_directories(${LMDB_INCLUDE})
+@@ -709,8 +709,12 @@ include_directories(${LMDB_INCLUDE})
include_directories(${LIBUNWIND_INCLUDE})
link_directories(${LIBUNWIND_LIBRARY_DIRS})
@@ -68,7 +69,7 @@ index e4f1159b5..14d398f87 100644
${device_headers}
device_ledger.hpp
diff --git a/src/device/device.cpp b/src/device/device.cpp
-index e6cd358b6..636929feb 100644
+index e6cd358b6..777584c01 100644
--- a/src/device/device.cpp
+++ b/src/device/device.cpp
@@ -29,7 +29,7 @@
@@ -85,7 +86,7 @@ index e6cd358b6..636929feb 100644
device_registry::device_registry(){
hw::core::register_all(registry);
- #ifdef WITH_DEVICE_LEDGER
-+ #if defined(WITH_DEVICE_LEDGER) || defined(HIDAPI_DUMMY)
++ #if defined(WITH_DEVICE_LEDGER) && !defined(HIDAPI_DUMMY)
hw::ledger::register_all(registry);
#endif
atexit(clear_device_registry);
@@ -130,7 +131,7 @@ index 392703a24..ffd419779 100644
diff --git a/src/device/device_io_dummy.cpp b/src/device/device_io_dummy.cpp
new file mode 100644
-index 000000000..fb082694e
+index 000000000..edb4beea3
--- /dev/null
+++ b/src/device/device_io_dummy.cpp
@@ -0,0 +1,133 @@
@@ -174,7 +175,7 @@ index 000000000..fb082694e
+// Data transport is made available in wallet2_api.h, so wallet developers can easily plug their
+// own USB/BLE/other transport layer.
+
-+#ifdef HIDAPI_DUMMY
++#if defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI)
+#include <boost/scope_exit.hpp>
+#include "log.hpp"
+#include "device_io_dummy.hpp"
@@ -349,7 +350,7 @@ index 000000000..a1733616d
+
+#endif // HAVE_HIDAPI
diff --git a/src/device/device_ledger.cpp b/src/device/device_ledger.cpp
-index 90675df11..136c6094b 100644
+index 8403d76e8..0587eb7d3 100644
--- a/src/device/device_ledger.cpp
+++ b/src/device/device_ledger.cpp
@@ -41,7 +41,7 @@ namespace hw {
@@ -370,18 +371,18 @@ index 90675df11..136c6094b 100644
this->mode = NONE;
this->has_view_key = false;
this->tx_in_progress = false;
-@@ -532,7 +532,9 @@ namespace hw {
+@@ -533,7 +533,9 @@ namespace hw {
bool device_ledger::connect(void) {
this->disconnect();
-+ #ifndef HIDAPI_DUMMY
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
hw_device.connect(known_devices);
+ #endif
this->reset();
#ifdef DEBUG_HWDEVICE
cryptonote::account_public_address pubkey;
diff --git a/src/device/device_ledger.hpp b/src/device/device_ledger.hpp
-index 03058c4f1..506f27c4a 100644
+index 03058c4f1..39454ca6d 100644
--- a/src/device/device_ledger.hpp
+++ b/src/device/device_ledger.hpp
@@ -35,6 +35,7 @@
@@ -405,7 +406,7 @@ index 03058c4f1..506f27c4a 100644
mutable boost::mutex command_locker;
//IO
-+#ifdef HIDAPI_DUMMY
++#if defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI)
+ hw::io::device_io_dummy hw_device;
+#else
hw::io::device_io_hid hw_device;
@@ -414,28 +415,28 @@ index 03058c4f1..506f27c4a 100644
unsigned char buffer_send[BUFFER_SEND_SIZE];
unsigned int length_recv;
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index 8bdd75a5a..09f91c5e2 100644
+index ee000e7ab..556e2a8ce 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
-@@ -49,6 +49,9 @@
+@@ -48,6 +48,9 @@
#include <boost/locale.hpp>
#include <boost/filesystem.hpp>
#include "bc-ur/src/bc-ur.hpp"
-+#ifdef HIDAPI_DUMMY
++#if defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI)
+#include "device/device_io_dummy.hpp"
+#endif
using namespace std;
using namespace cryptonote;
-@@ -3299,4 +3302,95 @@ uint64_t WalletImpl::getBytesSent()
+@@ -3178,4 +3181,95 @@ uint64_t WalletImpl::getBytesSent()
return m_wallet->get_bytes_sent();
}
+
+// HIDAPI_DUMMY
+bool WalletImpl::getStateIsConnected() {
-+ #ifndef HIDAPI_DUMMY
-+ setStatusError("MONERO compiled with -DHIDAPI_DUMMY");
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return false;
+ #else
+ return hw::io::device_io_dummy::stateIsConnected;
@@ -443,8 +444,8 @@ index 8bdd75a5a..09f91c5e2 100644
+}
+
+unsigned char* WalletImpl::getSendToDevice() {
-+ #ifndef HIDAPI_DUMMY
-+ setStatusError("MONERO compiled with -DHIDAPI_DUMMY");
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return {};
+ #else
+ return hw::io::device_io_dummy::sendToDevice;
@@ -452,8 +453,8 @@ index 8bdd75a5a..09f91c5e2 100644
+}
+
+size_t WalletImpl::getSendToDeviceLength() {
-+ #ifndef HIDAPI_DUMMY
-+ setStatusError("MONERO compiled with -DHIDAPI_DUMMY");
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return -1;
+ #else
+ return hw::io::device_io_dummy::sendToDeviceLength;
@@ -461,8 +462,8 @@ index 8bdd75a5a..09f91c5e2 100644
+}
+
+unsigned char* WalletImpl::getReceivedFromDevice() {
-+ #ifndef HIDAPI_DUMMY
-+ setStatusError("MONERO compiled with -DHIDAPI_DUMMY");
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return {};
+ #else
+ return hw::io::device_io_dummy::receivedFromDevice;
@@ -470,8 +471,8 @@ index 8bdd75a5a..09f91c5e2 100644
+}
+
+size_t WalletImpl::getReceivedFromDeviceLength() {
-+ #ifndef HIDAPI_DUMMY
-+ setStatusError("MONERO compiled with -DHIDAPI_DUMMY");
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return -1;
+ #else
+ return hw::io::device_io_dummy::receivedFromDeviceLength;
@@ -479,8 +480,8 @@ index 8bdd75a5a..09f91c5e2 100644
+}
+
+bool WalletImpl::getWaitsForDeviceSend() {
-+ #ifndef HIDAPI_DUMMY
-+ setStatusError("MONERO compiled with -DHIDAPI_DUMMY");
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return false;
+ #else
+ return hw::io::device_io_dummy::receivedFromDeviceLength;
@@ -488,8 +489,8 @@ index 8bdd75a5a..09f91c5e2 100644
+}
+
+bool WalletImpl::getWaitsForDeviceReceive() {
-+ #ifndef HIDAPI_DUMMY
-+ setStatusError("MONERO compiled with -DHIDAPI_DUMMY");
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return false;
+ #else
+ return hw::io::device_io_dummy::waitsForDeviceReceive;
@@ -497,8 +498,8 @@ index 8bdd75a5a..09f91c5e2 100644
+}
+
+void WalletImpl::setDeviceReceivedData(unsigned char* data, size_t len) {
-+ #ifndef HIDAPI_DUMMY
-+ setStatusError("MONERO compiled with -DHIDAPI_DUMMY");
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return;
+ #else
+ hw::io::device_io_dummy::receivedFromDevice = static_cast<unsigned char *>(malloc(len));
@@ -510,8 +511,8 @@ index 8bdd75a5a..09f91c5e2 100644
+}
+
+void WalletImpl::setDeviceSendData(unsigned char* data, size_t len) {
-+ #ifndef HIDAPI_DUMMY
-+ setStatusError("MONERO compiled with -DHIDAPI_DUMMY");
++ #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))
++ setStatusError("MONERO compiled with #if !(defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI))");
+ return;
+ #else
+ hw::io::device_io_dummy::sendToDevice = static_cast<unsigned char *>(malloc(len));
@@ -524,10 +525,10 @@ index 8bdd75a5a..09f91c5e2 100644
+
} // namespace
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
-index febc93119..9e1fbb40b 100644
+index edf8bb8ce..4e9c21ecb 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
-@@ -321,6 +321,24 @@ private:
+@@ -301,6 +301,24 @@ private:
// cache connection status to avoid unnecessary RPC calls
mutable std::atomic<bool> m_is_connected;
boost::optional<epee::net_utils::http::login> m_daemon_login{};
@@ -553,10 +554,10 @@ index febc93119..9e1fbb40b 100644
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
-index 2bbb32c8b..c8d6bb179 100644
+index 764adbfbf..53ec4abfc 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
-@@ -1204,6 +1204,18 @@ struct Wallet
+@@ -1150,6 +1150,18 @@ struct Wallet
//! get bytes sent
virtual uint64_t getBytesSent() = 0;
@@ -575,6 +576,29 @@ index 2bbb32c8b..c8d6bb179 100644
};
/**
+diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
+index e81b8f83a..277be6ac9 100644
+--- a/src/wallet/api/wallet_manager.cpp
++++ b/src/wallet/api/wallet_manager.cpp
+@@ -188,10 +188,14 @@ bool WalletManagerImpl::verifyWalletPassword(const std::string &keys_file_name,
+
+ bool WalletManagerImpl::queryWalletDevice(Wallet::Device& device_type, const std::string &keys_file_name, const std::string &password, uint64_t kdf_rounds) const
+ {
+- hw::device::device_type type;
+- bool r = tools::wallet2::query_device(type, keys_file_name, password, kdf_rounds);
+- device_type = static_cast<Wallet::Device>(type);
+- return r;
++ try {
++ hw::device::device_type type;
++ bool r = tools::wallet2::query_device(type, keys_file_name, password, kdf_rounds);
++ device_type = static_cast<Wallet::Device>(type);
++ return r;
++ } catch (...) {
++ return false;
++ }
+ }
+
+ std::vector<std::string> WalletManagerImpl::findWallets(const std::string &path)
--
-2.45.1.windows.1
+2.39.5 (Apple Git-154)
diff --git a/patches/wownero/0009-fix-missing-___clear_cache-when-targetting-iOS.patch b/patches/wownero/0009-fix-missing-___clear_cache-when-targetting-iOS.patch
deleted file mode 100644
index 513a105..0000000
--- a/patches/wownero/0009-fix-missing-___clear_cache-when-targetting-iOS.patch
+++ /dev/null
@@ -1,33 +0,0 @@
-From 05c6c9b1febdf4bb1073acd7b30d1ef981cd56b1 Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Tue, 2 Apr 2024 17:07:19 +0200
-Subject: [PATCH 09/14] fix missing ___clear_cache when targetting iOS
-
----
- .gitmodules | 5 ++---
- external/randomwow | 2 +-
- 2 files changed, 3 insertions(+), 4 deletions(-)
-
-diff --git a/.gitmodules b/.gitmodules
-index bd30f0444..6c3e36a72 100644
---- a/.gitmodules
-+++ b/.gitmodules
-@@ -20,6 +20,5 @@
- branch = monero
- [submodule "external/randomwow"]
- path = external/randomwow
-- url = https://github.com/wownero-mirror/RandomWOW
-- branch = 1.2.1-wow
--
-+ url = https://github.com/mrcyjanek/RandomWOW
-+ branch = cyjan-fix-ios
-diff --git a/external/randomwow b/external/randomwow
-index 27b099b6d..6f30d4b92 160000
---- a/external/randomwow
-+++ b/external/randomwow
-@@ -1 +1 @@
--Subproject commit 27b099b6dd6fef6e17f58c6dfe00009e9c5df587
-+Subproject commit 6f30d4b924fecb231e5b683915cc75d18b3b5866
---
-2.45.2
-
diff --git a/patches/wownero/0002-polyseed.patch b/patches/wownero/0009-polyseed.patch
index 302d392..aa5af28 100644
--- a/patches/wownero/0002-polyseed.patch
+++ b/patches/wownero/0009-polyseed.patch
@@ -1,36 +1,45 @@
-From 8729f36a109b33a080f5ee117a9d2a53fb55a47a Mon Sep 17 00:00:00 2001
+From c1f5cc2d9b71b7b923b17c33c23b23da918e4751 Mon Sep 17 00:00:00 2001
From: tobtoht <tob@featherwallet.org>
Date: Tue, 12 Mar 2024 09:42:37 +0100
-Subject: [PATCH 02/14] polyseed
+Subject: [PATCH 09/15] polyseed
Co-authored-by: Czarek Nakamoto <cyjan@mrcyjanek.net>
---
- .github/workflows/build.yml | 4 +-
- .gitmodules | 6 +
- CMakeLists.txt | 4 +-
- contrib/epee/include/wipeable_string.h | 7 +
- contrib/epee/src/wipeable_string.cpp | 10 ++
- external/CMakeLists.txt | 2 +
- external/polyseed | 1 +
- external/utf8proc | 1 +
- src/CMakeLists.txt | 1 +
- src/cryptonote_basic/CMakeLists.txt | 1 +
- src/cryptonote_basic/account.cpp | 23 +++-
- src/cryptonote_basic/account.h | 6 +
- src/cryptonote_config.h | 2 +
- src/polyseed/CMakeLists.txt | 25 ++++
- src/polyseed/pbkdf2.c | 85 ++++++++++++
- src/polyseed/pbkdf2.h | 46 +++++++
- src/polyseed/polyseed.cpp | 182 +++++++++++++++++++++++++
- src/polyseed/polyseed.hpp | 167 +++++++++++++++++++++++
- src/wallet/api/wallet.cpp | 71 ++++++++++
- src/wallet/api/wallet.h | 10 ++
- src/wallet/api/wallet2_api.h | 25 ++++
- src/wallet/api/wallet_manager.cpp | 9 ++
- src/wallet/api/wallet_manager.h | 10 ++
- src/wallet/wallet2.cpp | 102 ++++++++++++--
- src/wallet/wallet2.h | 30 +++-
- 25 files changed, 809 insertions(+), 21 deletions(-)
+ .gitmodules | 6 +
+ CMakeLists.txt | 4 +-
+ contrib/depends/hosts/darwin.mk | 2 +
+ contrib/depends/hosts/linux.mk | 8 +-
+ contrib/depends/packages/packages.mk | 2 +-
+ contrib/depends/packages/polyseed.mk | 28 +++
+ contrib/depends/packages/sodium.mk | 2 +-
+ .../polyseed/0001-disable-soname.patch | 48 +++++
+ .../patches/polyseed/force-static-mingw.patch | 23 +++
+ contrib/epee/include/wipeable_string.h | 7 +
+ contrib/epee/src/wipeable_string.cpp | 10 +
+ external/CMakeLists.txt | 2 +
+ external/polyseed | 1 +
+ external/utf8proc | 1 +
+ src/CMakeLists.txt | 1 +
+ src/cryptonote_basic/CMakeLists.txt | 1 +
+ src/cryptonote_basic/account.cpp | 23 ++-
+ src/cryptonote_basic/account.h | 6 +
+ src/cryptonote_config.h | 2 +
+ src/polyseed/CMakeLists.txt | 25 +++
+ src/polyseed/pbkdf2.c | 85 ++++++++
+ src/polyseed/pbkdf2.h | 46 +++++
+ src/polyseed/polyseed.cpp | 182 ++++++++++++++++++
+ src/polyseed/polyseed.hpp | 167 ++++++++++++++++
+ src/wallet/api/wallet.cpp | 70 +++++++
+ src/wallet/api/wallet.h | 10 +
+ src/wallet/api/wallet2_api.h | 25 +++
+ src/wallet/api/wallet_manager.cpp | 9 +
+ src/wallet/api/wallet_manager.h | 10 +
+ src/wallet/wallet2.cpp | 99 ++++++++--
+ src/wallet/wallet2.h | 30 ++-
+ 31 files changed, 912 insertions(+), 23 deletions(-)
+ create mode 100644 contrib/depends/packages/polyseed.mk
+ create mode 100644 contrib/depends/patches/polyseed/0001-disable-soname.patch
+ create mode 100644 contrib/depends/patches/polyseed/force-static-mingw.patch
create mode 160000 external/polyseed
create mode 160000 external/utf8proc
create mode 100644 src/polyseed/CMakeLists.txt
@@ -39,43 +48,26 @@ Co-authored-by: Czarek Nakamoto <cyjan@mrcyjanek.net>
create mode 100644 src/polyseed/polyseed.cpp
create mode 100644 src/polyseed/polyseed.hpp
-diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
-index 4c1e381c0..70bea03b3 100644
---- a/.github/workflows/build.yml
-+++ b/.github/workflows/build.yml
-@@ -124,8 +124,8 @@ jobs:
- - name: build
- run: |
- ${{env.CCACHE_SETTINGS}}
-- cmake .
-- make wallet_api -j3
-+ cmake -S . -B build
-+ cmake --build build wallet_api -j3
-
- test-ubuntu:
- needs: build-ubuntu
diff --git a/.gitmodules b/.gitmodules
-index e40b7b4c7..bd30f0444 100644
+index b24855d9b..589676649 100644
--- a/.gitmodules
+++ b/.gitmodules
-@@ -8,6 +8,12 @@
- active = false
- path = external/trezor-common
- url = https://github.com/trezor/trezor-common.git
+@@ -20,3 +20,9 @@
+ path = external/bc-ur
+ url = https://github.com/MrCyjaneK/bc-ur
+ branch = misc
+[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
+\ No newline at end of file
diff --git a/CMakeLists.txt b/CMakeLists.txt
-index 20829bc30..2dd427d3d 100644
+index abe44eca5..85a62ef7b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
-@@ -370,6 +370,8 @@ if(NOT MANUAL_SUBMODULES)
+@@ -372,6 +372,8 @@ if(NOT MANUAL_SUBMODULES)
#check_submodule(external/trezor-common)
check_submodule(external/randomwow)
check_submodule(external/supercop)
@@ -84,7 +76,7 @@ index 20829bc30..2dd427d3d 100644
endif()
endif()
-@@ -459,7 +461,7 @@ endif()
+@@ -461,7 +463,7 @@ endif()
# elseif(CMAKE_SYSTEM_NAME MATCHES ".*BSDI.*")
# set(BSDI TRUE)
@@ -93,6 +85,183 @@ index 20829bc30..2dd427d3d 100644
if(APPLE)
cmake_policy(SET CMP0042 NEW)
+diff --git a/contrib/depends/hosts/darwin.mk b/contrib/depends/hosts/darwin.mk
+index 83d83036b..b14ee5c5b 100644
+--- a/contrib/depends/hosts/darwin.mk
++++ b/contrib/depends/hosts/darwin.mk
+@@ -8,6 +8,8 @@ endif
+ darwin_CC=clang -target $(CC_target) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(host_prefix)/native/SDK/ -mlinker-version=$(LD64_VERSION) -B$(host_prefix)/native/bin/$(host)-
+ darwin_CXX=clang++ -target $(CC_target) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(host_prefix)/native/SDK/ -mlinker-version=$(LD64_VERSION) -stdlib=libc++ -B$(host_prefix)/native/bin/$(host)-
+
++darwin_RANLIB=$(host_prefix)/native/bin/$(host)-ranlib
++
+ darwin_CFLAGS=-pipe
+ darwin_CXXFLAGS=$(darwin_CFLAGS)
+ darwin_ARFLAGS=cr
+diff --git a/contrib/depends/hosts/linux.mk b/contrib/depends/hosts/linux.mk
+index 912fdb03c..b79799f30 100644
+--- a/contrib/depends/hosts/linux.mk
++++ b/contrib/depends/hosts/linux.mk
+@@ -11,15 +11,15 @@ linux_debug_CXXFLAGS=$(linux_debug_CFLAGS)
+ linux_debug_CPPFLAGS=-D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC
+
+ ifeq (86,$(findstring 86,$(build_arch)))
+-i686_linux_CC=gcc -m32
+-i686_linux_CXX=g++ -m32
++i686_linux_CC=i686-linux-gnu-gcc
++i686_linux_CXX=i686-linux-gnu-g++
+ i686_linux_AR=ar
+ i686_linux_RANLIB=ranlib
+ i686_linux_NM=nm
+ i686_linux_STRIP=strip
+
+-x86_64_linux_CC=gcc -m64
+-x86_64_linux_CXX=g++ -m64
++x86_64_linux_CC=x86_64-linux-gnu-gcc
++x86_64_linux_CXX=x86_64-linux-gnu-g++
+ x86_64_linux_AR=ar
+ x86_64_linux_RANLIB=ranlib
+ x86_64_linux_NM=nm
+diff --git a/contrib/depends/packages/packages.mk b/contrib/depends/packages/packages.mk
+index d2d1eca85..8783d4955 100644
+--- a/contrib/depends/packages/packages.mk
++++ b/contrib/depends/packages/packages.mk
+@@ -1,4 +1,4 @@
+-packages:=boost openssl zeromq libiconv expat unbound
++packages:=boost openssl zeromq libiconv expat unbound polyseed
+
+ # ccache is useless in gitian builds
+ ifneq ($(GITIAN),1)
+diff --git a/contrib/depends/packages/polyseed.mk b/contrib/depends/packages/polyseed.mk
+new file mode 100644
+index 000000000..0071b20f3
+--- /dev/null
++++ b/contrib/depends/packages/polyseed.mk
+@@ -0,0 +1,28 @@
++package=polyseed
++$(package)_version=2.0.0
++$(package)_download_path=https://github.com/tevador/$(package)/archive/refs/tags/
++$(package)_download_file=v$($(package)_version).tar.gz
++$(package)_file_name=$(package)-$($(package)_version).tar.gz
++$(package)_sha256_hash=f36282fcbcd68d32461b8230c89e1a40661bd46b91109681cec637433004135a
++$(package)_patches=force-static-mingw.patch 0001-disable-soname.patch
++
++define $(package)_preprocess_cmds
++ patch -p1 < $($(package)_patch_dir)/force-static-mingw.patch &&\
++ patch -p1 < $($(package)_patch_dir)/0001-disable-soname.patch
++endef
++
++define $(package)_config_cmds
++ CC="$($(package)_cc)" cmake -DCMAKE_INSTALL_PREFIX="$(host_prefix)" .
++endef
++
++define $(package)_set_vars
++ $(package)_build_opts=CC="$($(package)_cc)"
++endef
++
++define $(package)_build_cmds
++ CC="$($(package)_cc)" $(MAKE)
++endef
++
++define $(package)_stage_cmds
++ $(MAKE) DESTDIR=$($(package)_staging_dir) install
++endef
+diff --git a/contrib/depends/packages/sodium.mk b/contrib/depends/packages/sodium.mk
+index 87b34599e..68a5b48ba 100644
+--- a/contrib/depends/packages/sodium.mk
++++ b/contrib/depends/packages/sodium.mk
+@@ -6,7 +6,7 @@ $(package)_sha256_hash=6f504490b342a4f8a4c4a02fc9b866cbef8622d5df4e5452b46be121e
+ $(package)_patches=disable-glibc-getrandom-getentropy.patch fix-whitespace.patch
+
+ define $(package)_set_vars
+-$(package)_config_opts=--enable-static --disable-shared
++$(package)_config_opts=--enable-static --disable-shared --with-pic
+ $(package)_config_opts+=--prefix=$(host_prefix)
+ endef
+
+diff --git a/contrib/depends/patches/polyseed/0001-disable-soname.patch b/contrib/depends/patches/polyseed/0001-disable-soname.patch
+new file mode 100644
+index 000000000..bd97dd394
+--- /dev/null
++++ b/contrib/depends/patches/polyseed/0001-disable-soname.patch
+@@ -0,0 +1,48 @@
++From aabafcfc0572651436d024a635483c49042fad7f Mon Sep 17 00:00:00 2001
++From: Czarek Nakamoto <cyjan@mrcyjanek.net>
++Date: Thu, 28 Mar 2024 00:32:51 +0100
++Subject: [PATCH] disable soname
++
++---
++ CMakeLists.txt | 16 +++++++++-------
++ 1 file changed, 9 insertions(+), 7 deletions(-)
++
++diff --git a/CMakeLists.txt b/CMakeLists.txt
++index 8a8e7c2..5301353 100644
++--- a/CMakeLists.txt
+++++ b/CMakeLists.txt
++@@ -36,6 +36,7 @@ include_directories(polyseed
++ target_compile_definitions(polyseed PRIVATE POLYSEED_SHARED)
++ set_target_properties(polyseed PROPERTIES VERSION 2.0.0
++ SOVERSION 2
+++ NO_SONAME 1
++ C_STANDARD 11
++ C_STANDARD_REQUIRED ON)
++
++@@ -45,16 +46,17 @@ include_directories(polyseed_static
++ include/)
++ target_compile_definitions(polyseed_static PRIVATE POLYSEED_STATIC)
++ set_target_properties(polyseed_static PROPERTIES OUTPUT_NAME polyseed
+++ NO_SONAME 1
++ C_STANDARD 11
++ C_STANDARD_REQUIRED ON)
++
++-add_executable(polyseed-tests
++- tests/tests.c)
++-include_directories(polyseed-tests
++- include/)
++-target_compile_definitions(polyseed-tests PRIVATE POLYSEED_STATIC)
++-target_link_libraries(polyseed-tests
++- PRIVATE polyseed_static)
+++# add_executable(polyseed-tests
+++# tests/tests.c)
+++# include_directories(polyseed-tests
+++# include/)
+++# target_compile_definitions(polyseed-tests PRIVATE POLYSEED_STATIC)
+++# target_link_libraries(polyseed-tests
+++# PRIVATE polyseed_static)
++
++ include(GNUInstallDirs)
++ install(TARGETS polyseed polyseed_static
++--
++2.39.2
+diff --git a/contrib/depends/patches/polyseed/force-static-mingw.patch b/contrib/depends/patches/polyseed/force-static-mingw.patch
+new file mode 100644
+index 000000000..f05cb2b6a
+--- /dev/null
++++ b/contrib/depends/patches/polyseed/force-static-mingw.patch
+@@ -0,0 +1,23 @@
++--- a/include/polyseed.h
+++++ b/include/polyseed.h
++@@ -93,13 +93,13 @@ Shared/static library definitions
++ - define POLYSEED_STATIC when linking to the static library
++ */
++ #if defined(_WIN32) || defined(__CYGWIN__)
++- #ifdef POLYSEED_SHARED
++- #define POLYSEED_API __declspec(dllexport)
++- #elif !defined(POLYSEED_STATIC)
++- #define POLYSEED_API __declspec(dllimport)
++- #else
++- #define POLYSEED_API
++- #endif
+++// #ifdef POLYSEED_SHARED
+++// #define POLYSEED_API __declspec(dllexport)
+++// #elif !defined(POLYSEED_STATIC)
+++// #define POLYSEED_API __declspec(dllimport)
+++// #else
+++ #define POLYSEED_API
+++// #endif
++ #define POLYSEED_PRIVATE
++ #else
++ #ifdef POLYSEED_SHARED
diff --git a/contrib/epee/include/wipeable_string.h b/contrib/epee/include/wipeable_string.h
index 65977cd97..594e15de4 100644
--- a/contrib/epee/include/wipeable_string.h
@@ -138,29 +307,30 @@ index b016f2f48..f2f365b1b 100644
+
}
diff --git a/external/CMakeLists.txt b/external/CMakeLists.txt
-index 29aed0cc6..04910a4fc 100644
+index 88a7bb0b5..95be500b1 100644
--- a/external/CMakeLists.txt
+++ b/external/CMakeLists.txt
-@@ -70,3 +70,5 @@ add_subdirectory(db_drivers)
+@@ -73,4 +73,6 @@ add_subdirectory(db_drivers)
add_subdirectory(easylogging++)
add_subdirectory(qrcodegen)
- add_subdirectory(randomwow EXCLUDE_FROM_ALL)
+ add_subdirectory(bc-ur)
+add_subdirectory(polyseed EXCLUDE_FROM_ALL)
+add_subdirectory(utf8proc EXCLUDE_FROM_ALL)
+ add_subdirectory(randomwow EXCLUDE_FROM_ALL)
diff --git a/external/polyseed b/external/polyseed
new file mode 160000
-index 000000000..9d4f1a032
+index 000000000..bd79f5014
--- /dev/null
+++ b/external/polyseed
@@ -0,0 +1 @@
-+Subproject commit 9d4f1a032585656e1a642ee70cdf929001badba6
++Subproject commit bd79f5014c331273357277ed8a3d756fb61b9fa1
diff --git a/external/utf8proc b/external/utf8proc
new file mode 160000
-index 000000000..1cb28a66c
+index 000000000..3de4596fb
--- /dev/null
+++ b/external/utf8proc
@@ -0,0 +1 @@
-+Subproject commit 1cb28a66ca79a0845e99433fd1056257456cef8b
++Subproject commit 3de4596fbe28956855df2ecb3c11c0bbc3535838
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 9216bcaa5..c043ba150 100644
--- a/src/CMakeLists.txt
@@ -186,7 +356,7 @@ index 1414be1b2..414936a05 100644
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_SERIALIZATION_LIBRARY}
diff --git a/src/cryptonote_basic/account.cpp b/src/cryptonote_basic/account.cpp
-index 2ac455fda..4931c3740 100644
+index 4e87d4477..2d556f285 100644
--- a/src/cryptonote_basic/account.cpp
+++ b/src/cryptonote_basic/account.cpp
@@ -87,12 +87,16 @@ DISABLE_VS_WARNINGS(4244 4345)
@@ -215,8 +385,8 @@ index 2ac455fda..4931c3740 100644
+ m_keys.m_passphrase.wipe();
}
//-----------------------------------------------------------------
- crypto::secret_key account_base::generate(const crypto::secret_key& recovery_key, bool recover, bool two_random)
-@@ -244,6 +250,21 @@ DISABLE_VS_WARNINGS(4244 4345)
+ void account_base::set_spend_key(const crypto::secret_key& spend_secret_key)
+@@ -255,6 +261,21 @@ DISABLE_VS_WARNINGS(4244 4345)
create_from_keys(address, fake, viewkey);
}
//-----------------------------------------------------------------
@@ -239,7 +409,7 @@ index 2ac455fda..4931c3740 100644
{
m_keys.m_account_address.m_spend_public_key = spend_public_key;
diff --git a/src/cryptonote_basic/account.h b/src/cryptonote_basic/account.h
-index 2ee9545d4..0099ebfe7 100644
+index 93d1d28f0..1f76febce 100644
--- a/src/cryptonote_basic/account.h
+++ b/src/cryptonote_basic/account.h
@@ -33,6 +33,7 @@
@@ -277,7 +447,7 @@ 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..5b36c70de 100644
+index 8b5091a46..d9151e8d2 100644
--- a/src/cryptonote_config.h
+++ b/src/cryptonote_config.h
@@ -219,6 +219,8 @@
@@ -828,10 +998,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 556e2a8ce..704e5e148 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
+@@ -728,6 +728,28 @@ bool WalletImpl::recoverFromDevice(const std::string &path, const std::string &p
return true;
}
@@ -860,35 +1030,35 @@ 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
- return std::string(seed.data(), seed.size()); // TODO
+@@ -845,6 +867,54 @@ std::string WalletImpl::seed(const std::string& seed_offset) const
+ }
}
+bool WalletImpl::getPolyseed(std::string &seed_words, std::string &passphrase) const
+{
-+ epee::wipeable_string seed_words_epee(seed_words.c_str(), seed_words.size());
-+ epee::wipeable_string passphrase_epee(passphrase.c_str(), passphrase.size());
-+ clearStatus();
++ epee::wipeable_string seed_words_epee(seed_words.c_str(), seed_words.size());
++ epee::wipeable_string passphrase_epee(passphrase.c_str(), passphrase.size());
++ clearStatus();
+
-+ if (!m_wallet) {
-+ return false;
-+ }
++ if (!m_wallet) {
++ return false;
++ }
+
-+ bool result = m_wallet->get_polyseed(seed_words_epee, passphrase_epee);
++ 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());
++ seed_words.assign(seed_words_epee.data(), seed_words_epee.size());
++ passphrase.assign(passphrase_epee.data(), passphrase_epee.size());
+
-+ return result;
++ return result;
+}
+
+std::vector<std::pair<std::string, std::string>> Wallet::getPolyseedLanguages()
-+{
++ {
+ std::vector<std::pair<std::string, std::string>> languages;
+
+ auto langs = polyseed::get_langs();
+ for (const auto &lang : langs) {
-+ languages.emplace_back(std::pair<std::string, std::string>(lang.name_en(), lang.name()));
++ languages.emplace_back(std::pair<std::string, std::string>(lang.name_en(), lang.name()));
+ }
+
+ return languages;
@@ -896,31 +1066,30 @@ 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());
++ epee::wipeable_string seed_words_epee(seed_words.c_str(), seed_words.size());
+
-+ try {
-+ polyseed::data polyseed(POLYSEED_COIN);
-+ polyseed.create(0);
-+ polyseed.encode(polyseed::get_lang_by_name(language), seed_words_epee);
++ try {
++ polyseed::data polyseed(POLYSEED_COIN);
++ polyseed.create(0);
++ polyseed.encode(polyseed::get_lang_by_name(language), seed_words_epee);
+
-+ seed_words.assign(seed_words_epee.data(), seed_words_epee.size());
-+ }
-+ catch (const std::exception &e) {
-+ err = e.what();
-+ return false;
-+ }
++ seed_words.assign(seed_words_epee.data(), seed_words_epee.size());
++ }
++ catch (const std::exception &e) {
++ err = e.what();
++ return false;
++ }
+
-+ return true;
++ return true;
+}
-+
std::string WalletImpl::getSeedLanguage() const
{
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 4e9c21ecb..32e12284b 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 +1110,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 53ec4abfc..be1c3704e 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
-@@ -800,6 +800,10 @@ struct Wallet
+@@ -709,6 +709,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 +1124,7 @@ index 6df661dc2..a0ed60a39 100644
/**
* @brief StartRefresh - Start/resume refresh thread (refresh every 10 seconds)
*/
-@@ -1432,6 +1436,27 @@ struct WalletManager
+@@ -1320,6 +1324,27 @@ struct WalletManager
uint64_t kdf_rounds = 1,
WalletListener * listener = nullptr) = 0;
@@ -984,10 +1153,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 277be6ac9..da2056d8a 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 +1173,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 +1194,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..dfcc206a0 100644
+index 671fa5298..3e49c21f8 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -92,6 +92,7 @@ using namespace epee;
@@ -1036,7 +1205,7 @@ index e586d67f7..dfcc206a0 100644
extern "C"
{
-@@ -1272,7 +1273,8 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std
+@@ -1278,7 +1279,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),
@@ -1046,63 +1215,56 @@ index e586d67f7..dfcc206a0 100644
{
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
- key = cryptonote::encrypt_key(key, passphrase);
- if (!crypto::ElectrumWords::bytes_to_words(key, electrum_words, seed_language))
- {
-- std::cout << "Failed to create seed from key for language: " << seed_language << std::endl;
-+ std::cout << "Failed to create seed from key for language: " << seed_language << ", falling back to English." << std::endl;
-+ crypto::ElectrumWords::bytes_to_words(key, electrum_words, "English");
-+ }
+@@ -1474,6 +1476,20 @@ bool wallet2::get_seed(epee::wipeable_string& electrum_words, const epee::wipeab
+ return true;
+ }
+ //----------------------------------------------------------------------------------------------------
+
-+ return true;
-+}
-+//----------------------------------------------------------------------------------------------------
+bool wallet2::get_polyseed(epee::wipeable_string& polyseed, epee::wipeable_string& passphrase) const
+{
+ if (!m_polyseed) {
- return false;
- }
-
++ return false;
++ }
++
+ polyseed::data data(POLYSEED_COIN);
+ data.load(get_account().get_keys().m_polyseed);
+ data.encode(polyseed::get_lang_by_name(seed_language), polyseed);
-+
+ passphrase = get_account().get_keys().m_passphrase;
-+
- return true;
- }
- //----------------------------------------------------------------------------------------------------
-@@ -4712,6 +4729,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const epee:
++ return true;
++}
++//----------------------------------------------------------------------------------------------------
+ bool wallet2::get_multisig_seed(epee::wipeable_string& seed, const epee::wipeable_string &passphrase) const
+ {
+ bool ready;
+@@ -4792,6 +4808,9 @@ boost::optional<wallet2::keys_file_data> wallet2::get_keys_file_data(const crypt
value2.SetInt(m_enable_multisig ? 1 : 0);
json.AddMember("enable_multisig", value2, json.GetAllocator());
+ value2.SetInt(m_polyseed ? 1 : 0);
+ json.AddMember("polyseed", value2, json.GetAllocator());
+
- // Serialize the JSON object
- rapidjson::StringBuffer buffer;
- rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
-@@ -4859,7 +4879,8 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
- m_auto_mine_for_rpc_payment_threshold = -1.0f;
- m_credits_target = 0;
+ 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());
+@@ -5031,6 +5050,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_allow_mismatched_daemon_version = false;
+ m_allow_mismatched_daemon_version = true;
+ m_custom_background_key = boost::none;
+ 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
- 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;
+@@ -5271,6 +5291,9 @@ bool wallet2::load_keys_buf(const std::string& keys_buf, const epee::wipeable_st
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, background_sync_type, BackgroundSyncType, Int, false, BackgroundSyncOff);
+ m_background_sync_type = field_background_sync_type;
+
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, polyseed, int, Int, false, false);
+ m_polyseed = field_polyseed;
- }
- else
- {
-@@ -5370,6 +5393,48 @@ void wallet2::init_type(hw::device::device_type device_type)
++
+ // Load encryption key used to encrypt background cache
+ crypto::chacha_key custom_background_key;
+ m_custom_background_key = boost::none;
+@@ -5590,6 +5613,48 @@ void wallet2::init_type(hw::device::device_type device_type)
m_key_device_type = device_type;
}
@@ -1151,7 +1313,7 @@ index e586d67f7..dfcc206a0 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
+@@ -5717,7 +5782,7 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const epee::wip
return retval;
}
@@ -1160,7 +1322,7 @@ index e586d67f7..dfcc206a0 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
+@@ -5741,7 +5806,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.
@@ -1169,7 +1331,7 @@ index e586d67f7..dfcc206a0 100644
uint64_t target_height = get_daemon_blockchain_target_height(err);
if (err.empty()) {
if (target_height < height)
-@@ -13546,7 +13611,7 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err)
+@@ -13634,9 +13699,10 @@ uint64_t wallet2::get_daemon_blockchain_target_height(string &err)
return target_height;
}
@@ -1177,8 +1339,11 @@ index e586d67f7..dfcc206a0 100644
+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 = fork_block + ((t > 0 ? t : time(NULL)) - fork_time)/seconds_per_block;
LOG_PRINT_L2("Calculated blockchain height: " << approx_blockchain_height);
-@@ -15262,15 +15327,6 @@ bool wallet2::parse_uri(const std::string &uri, std::string &address, std::strin
+ return approx_blockchain_height;
+ }
+@@ -15771,15 +15837,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)
{
@@ -1194,7 +1359,7 @@ index e586d67f7..dfcc206a0 100644
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
+@@ -15788,7 +15845,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");
}
@@ -1219,7 +1384,7 @@ index e586d67f7..dfcc206a0 100644
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 80ff0698d..c26349ce3 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -72,6 +72,7 @@
@@ -1230,7 +1395,7 @@ index df34f9abf..db5c1feb3 100644
#undef MONERO_DEFAULT_LOG_CATEGORY
#define MONERO_DEFAULT_LOG_CATEGORY "wallet.wallet2"
-@@ -854,6 +855,20 @@ private:
+@@ -921,6 +922,20 @@ private:
void generate(const std::string& wallet_, const epee::wipeable_string& password,
const epee::wipeable_string& multisig_data, bool create_address_file = false);
@@ -1251,7 +1416,7 @@ index df34f9abf..db5c1feb3 100644
/*!
* \brief Generates a wallet or restores one.
* \param wallet_ Name of wallet file
-@@ -1018,6 +1033,15 @@ private:
+@@ -1088,6 +1103,15 @@ private:
bool is_deterministic() const;
bool get_seed(epee::wipeable_string& electrum_words, const epee::wipeable_string &passphrase = epee::wipeable_string()) const;
@@ -1267,7 +1432,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:
+@@ -1555,8 +1579,8 @@ private:
/*!
* \brief Calculates the approximate blockchain height from current date/time.
*/
@@ -1278,7 +1443,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:
+@@ -1650,6 +1674,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 +1451,7 @@ index df34f9abf..db5c1feb3 100644
bool is_synced();
-@@ -1900,6 +1925,7 @@ private:
+@@ -1995,6 +2020,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 */
@@ -1295,5 +1460,5 @@ index df34f9abf..db5c1feb3 100644
uint32_t m_multisig_threshold;
std::vector<crypto::public_key> m_multisig_signers;
--
-2.45.2
+2.39.5 (Apple Git-154)
diff --git a/patches/wownero/0010-build-wownero-seed.patch b/patches/wownero/0010-build-wownero-seed.patch
deleted file mode 100644
index 95b6d49..0000000
--- a/patches/wownero/0010-build-wownero-seed.patch
+++ /dev/null
@@ -1,613 +0,0 @@
-From 6b220ce6f3bb9f57375d6bf06b70f82f043856c8 Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Thu, 25 Apr 2024 10:06:04 +0200
-Subject: [PATCH 10/14] build wownero-seed
-
----
- contrib/depends/hosts/android.mk | 3 +-
- contrib/depends/hosts/darwin.mk | 1 +
- contrib/depends/hosts/mingw32.mk | 3 +
- contrib/depends/packages/packages.mk | 2 +-
- contrib/depends/packages/wownero_seed.mk | 35 ++
- .../0001-fix-duplicate-symbol-error.patch | 497 ++++++++++++++++++
- 6 files changed, 539 insertions(+), 2 deletions(-)
- create mode 100644 contrib/depends/packages/wownero_seed.mk
- create mode 100644 contrib/depends/patches/wownero_seed/0001-fix-duplicate-symbol-error.patch
-
-diff --git a/contrib/depends/hosts/android.mk b/contrib/depends/hosts/android.mk
-index d6f8b99dd..5b2309972 100644
---- a/contrib/depends/hosts/android.mk
-+++ b/contrib/depends/hosts/android.mk
-@@ -6,7 +6,8 @@ endif
-
- android_CC=$(host_toolchain)clang
- android_CXX=$(host_toolchain)clang++
--android_RANLIB=:
-+android_RANLIB=$(host_toolchain)ranlib
-+android_AR=$(host_toolchain)ar
-
- android_CFLAGS=-pipe
- android_CXXFLAGS=$(android_CFLAGS)
-diff --git a/contrib/depends/hosts/darwin.mk b/contrib/depends/hosts/darwin.mk
-index cbe795081..ce2f5669d 100644
---- a/contrib/depends/hosts/darwin.mk
-+++ b/contrib/depends/hosts/darwin.mk
-@@ -9,6 +9,7 @@ darwin_CC=clang -target $(CC_target) -mmacosx-version-min=$(OSX_MIN_VERSION) --s
- darwin_CXX=clang++ -target $(CC_target) -mmacosx-version-min=$(OSX_MIN_VERSION) --sysroot $(host_prefix)/native/SDK/ -mlinker-version=$(LD64_VERSION) -stdlib=libc++ -B$(host_prefix)/native/bin/$(host)-
-
- darwin_RANLIB=$(host_prefix)/native/bin/$(host)-ranlib
-+darwin_AR=$(host_prefix)/native/bin/$(host)-ar
-
- darwin_CFLAGS=-pipe
- darwin_CXXFLAGS=$(darwin_CFLAGS)
-diff --git a/contrib/depends/hosts/mingw32.mk b/contrib/depends/hosts/mingw32.mk
-index ccc4c5082..4677694a6 100644
---- a/contrib/depends/hosts/mingw32.mk
-+++ b/contrib/depends/hosts/mingw32.mk
-@@ -2,6 +2,9 @@ mingw32_CFLAGS=-pipe
- mingw32_CXXFLAGS=$(mingw32_CFLAGS)
- mingw32_ARFLAGS=cr
-
-+mingw32_RANLIB=$(shell which $(host)-ranlib)
-+mingw32_AR=$(shell which $(host)-ar)
-+
- mingw32_release_CFLAGS=-O2
- mingw32_release_CXXFLAGS=$(mingw32_release_CFLAGS)
-
-diff --git a/contrib/depends/packages/packages.mk b/contrib/depends/packages/packages.mk
-index 8783d4955..3d513c5a2 100644
---- a/contrib/depends/packages/packages.mk
-+++ b/contrib/depends/packages/packages.mk
-@@ -1,4 +1,4 @@
--packages:=boost openssl zeromq libiconv expat unbound polyseed
-+packages:=boost openssl zeromq libiconv expat unbound polyseed wownero_seed
-
- # ccache is useless in gitian builds
- ifneq ($(GITIAN),1)
-diff --git a/contrib/depends/packages/wownero_seed.mk b/contrib/depends/packages/wownero_seed.mk
-new file mode 100644
-index 000000000..b376f80c5
---- /dev/null
-+++ b/contrib/depends/packages/wownero_seed.mk
-@@ -0,0 +1,35 @@
-+package=wownero_seed
-+$(package)_version=0.3.0
-+$(package)_download_path=https://github.com/MrCyjaneK/wownero-seed/archive/
-+$(package)_download_file=d3f68be347facfeebbd8f68fd74982c705cb917b.tar.gz
-+$(package)_file_name=$(package)-$($(package)_version).tar.gz
-+$(package)_sha256_hash=3b59ccde08e0fee204680240af4b270a18a677aa0e6036a3504570193d232406
-+$(package)_patches=0001-fix-duplicate-symbol-error.patch
-+
-+define $(package)_preprocess_cmds
-+ patch -p1 < $($(package)_patch_dir)/0001-fix-duplicate-symbol-error.patch
-+endef
-+
-+
-+ifeq ($(host_os),darwin)
-+ define $(package)_config_cmds
-+ CC="$($(package)_cc)" CXX="$($(package)_cxx)" cmake -DCMAKE_RANLIB="$($(package)_ranlib)" -DCMAKE_AR="$($(package)_ar)" -DCMAKE_INSTALL_PREFIX="$(host_prefix)" -DCMAKE_POSITION_INDEPENDENT_CODE=ON .
-+ endef
-+else
-+ define $(package)_config_cmds
-+ CC="$($(package)_cc)" CXX="$($(package)_cxx)" cmake -DCMAKE_INSTALL_PREFIX="$(host_prefix)" -DCMAKE_POSITION_INDEPENDENT_CODE=ON .
-+ endef
-+endif
-+
-+define $(package)_set_vars
-+ $(package)_build_opts=CC="$($(package)_cc)" CXX="$($(package)_cxx)"
-+endef
-+
-+
-+define $(package)_build_cmds
-+ CC="$($(package)_cc)" CXX="$($(package)_cxx)" $(MAKE) VERBOSE=1
-+endef
-+
-+define $(package)_stage_cmds
-+ CC="$($(package)_cc)" CXX="$($(package)_cxx)" $(MAKE) DESTDIR=$($(package)_staging_dir) install
-+endef
-diff --git a/contrib/depends/patches/wownero_seed/0001-fix-duplicate-symbol-error.patch b/contrib/depends/patches/wownero_seed/0001-fix-duplicate-symbol-error.patch
-new file mode 100644
-index 000000000..a8f8fe059
---- /dev/null
-+++ b/contrib/depends/patches/wownero_seed/0001-fix-duplicate-symbol-error.patch
-@@ -0,0 +1,497 @@
-+From 4be93209afb80b11834a0849391ee6eeb68aec4a Mon Sep 17 00:00:00 2001
-+From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-+Date: Thu, 25 Apr 2024 09:37:37 +0200
-+Subject: [PATCH] fix duplicate symbol error
-+
-+---
-+ src/argon2/argon2.c | 8 +++---
-+ src/argon2/argon2.h | 4 +--
-+ src/argon2/blake2/blake2.h | 12 ++++-----
-+ src/argon2/blake2/blake2b.c | 46 ++++++++++++++++----------------
-+ src/argon2/core.c | 52 ++++++++++++++++++-------------------
-+ src/argon2/core.h | 17 ++++++------
-+ src/argon2/ref.c | 2 +-
-+ 7 files changed, 70 insertions(+), 71 deletions(-)
-+
-+diff --git a/src/argon2/argon2.c b/src/argon2/argon2.c
-+index e9882b7..470dc26 100644
-+--- a/src/argon2/argon2.c
-++++ b/src/argon2/argon2.c
-+@@ -37,7 +37,7 @@ const char *argon2_type2string(argon2_type type, int uppercase) {
-+
-+ int argon2_ctx(argon2_context *context, argon2_type type) {
-+ /* 1. Validate all inputs */
-+- int result = validate_inputs(context);
-++ int result = validate_inputs_wowseed(context);
-+ uint32_t memory_blocks, segment_length;
-+ argon2_instance_t instance;
-+
-+@@ -78,20 +78,20 @@ int argon2_ctx(argon2_context *context, argon2_type type) {
-+ /* 3. Initialization: Hashing inputs, allocating memory, filling first
-+ * blocks
-+ */
-+- result = initialize(&instance, context);
-++ result = initialize_wowseed(&instance, context);
-+
-+ if (ARGON2_OK != result) {
-+ return result;
-+ }
-+
-+ /* 4. Filling memory */
-+- result = fill_memory_blocks(&instance);
-++ result = _fill_memory_blocks_wowseed(&instance);
-+
-+ if (ARGON2_OK != result) {
-+ return result;
-+ }
-+ /* 5. Finalization */
-+- finalize(context, &instance);
-++ finalize_wowseed(context, &instance);
-+
-+ return ARGON2_OK;
-+ }
-+diff --git a/src/argon2/argon2.h b/src/argon2/argon2.h
-+index 1b471f6..f60e269 100644
-+--- a/src/argon2/argon2.h
-++++ b/src/argon2/argon2.h
-+@@ -185,7 +185,7 @@ typedef void (*deallocate_fptr)(uint8_t *memory, size_t bytes_to_allocate);
-+ * 4 parallel lanes.
-+ * You want to erase the password, but you're OK with last pass not being
-+ * erased. You want to use the default memory allocator.
-+- * Then you initialize:
-++ * Then you initialize_wowseed:
-+ Argon2_Context(out,8,pwd,32,salt,16,NULL,0,NULL,0,5,1<<20,4,4,NULL,NULL,true,false,false,false)
-+ */
-+ typedef struct Argon2_Context {
-+@@ -329,7 +329,7 @@ ARGON2_PUBLIC int argon2_hash(const uint32_t t_cost, const uint32_t m_cost,
-+
-+ /**
-+ * Verifies a password against an encoded string
-+- * Encoded string is restricted as in validate_inputs()
-++ * Encoded string is restricted as in validate_inputs_wowseed()
-+ * @param encoded String encoding parameters, salt, hash
-+ * @param pwd Pointer to password
-+ * @pre Returns ARGON2_OK if successful
-+diff --git a/src/argon2/blake2/blake2.h b/src/argon2/blake2/blake2.h
-+index 9f97e1c..25b445d 100644
-+--- a/src/argon2/blake2/blake2.h
-++++ b/src/argon2/blake2/blake2.h
-+@@ -67,15 +67,15 @@ enum {
-+ };
-+
-+ /* Streaming API */
-+-ARGON2_LOCAL int blake2b_init(blake2b_state *S, size_t outlen);
-+-ARGON2_LOCAL int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
-++ARGON2_LOCAL int blake2b_init_wowseed(blake2b_state *S, size_t outlen);
-++ARGON2_LOCAL int blake2b_init_key_wowseed(blake2b_state *S, size_t outlen, const void *key,
-+ size_t keylen);
-+-ARGON2_LOCAL int blake2b_init_param(blake2b_state *S, const blake2b_param *P);
-+-ARGON2_LOCAL int blake2b_update(blake2b_state *S, const void *in, size_t inlen);
-+-ARGON2_LOCAL int blake2b_final(blake2b_state *S, void *out, size_t outlen);
-++ARGON2_LOCAL int blake2b_init_param_wowseed(blake2b_state *S, const blake2b_param *P);
-++ARGON2_LOCAL int blake2b_update_wowseed(blake2b_state *S, const void *in, size_t inlen);
-++ARGON2_LOCAL int blake2b_final_wowseed(blake2b_state *S, void *out, size_t outlen);
-+
-+ /* Simple API */
-+-ARGON2_LOCAL int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
-++ARGON2_LOCAL int blake2b_wowseed(void *out, size_t outlen, const void *in, size_t inlen,
-+ const void *key, size_t keylen);
-+
-+ /* Argon2 Team - Begin Code */
-+diff --git a/src/argon2/blake2/blake2b.c b/src/argon2/blake2/blake2b.c
-+index ca05df5..8138b86 100644
-+--- a/src/argon2/blake2/blake2b.c
-++++ b/src/argon2/blake2/blake2b.c
-+@@ -70,7 +70,7 @@ static BLAKE2_INLINE void blake2b_init0(blake2b_state *S) {
-+ memcpy(S->h, blake2b_IV, sizeof(S->h));
-+ }
-+
-+-int blake2b_init_param(blake2b_state *S, const blake2b_param *P) {
-++int blake2b_init_param_wowseed(blake2b_state *S, const blake2b_param *P) {
-+ const unsigned char *p = (const unsigned char *)P;
-+ unsigned int i;
-+
-+@@ -88,7 +88,7 @@ int blake2b_init_param(blake2b_state *S, const blake2b_param *P) {
-+ }
-+
-+ /* Sequential blake2b initialization */
-+-int blake2b_init(blake2b_state *S, size_t outlen) {
-++int blake2b_init_wowseed(blake2b_state *S, size_t outlen) {
-+ blake2b_param P;
-+
-+ if (S == NULL) {
-+@@ -113,10 +113,10 @@ int blake2b_init(blake2b_state *S, size_t outlen) {
-+ memset(P.salt, 0, sizeof(P.salt));
-+ memset(P.personal, 0, sizeof(P.personal));
-+
-+- return blake2b_init_param(S, &P);
-++ return blake2b_init_param_wowseed(S, &P);
-+ }
-+
-+-int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
-++int blake2b_init_key_wowseed(blake2b_state *S, size_t outlen, const void *key,
-+ size_t keylen) {
-+ blake2b_param P;
-+
-+@@ -147,7 +147,7 @@ int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
-+ memset(P.salt, 0, sizeof(P.salt));
-+ memset(P.personal, 0, sizeof(P.personal));
-+
-+- if (blake2b_init_param(S, &P) < 0) {
-++ if (blake2b_init_param_wowseed(S, &P) < 0) {
-+ blake2b_invalidate_state(S);
-+ return -1;
-+ }
-+@@ -156,7 +156,7 @@ int blake2b_init_key(blake2b_state *S, size_t outlen, const void *key,
-+ uint8_t block[BLAKE2B_BLOCKBYTES];
-+ memset(block, 0, BLAKE2B_BLOCKBYTES);
-+ memcpy(block, key, keylen);
-+- blake2b_update(S, block, BLAKE2B_BLOCKBYTES);
-++ blake2b_update_wowseed(S, block, BLAKE2B_BLOCKBYTES);
-+ /* Burn the key from stack */
-+ clear_internal_memory(block, BLAKE2B_BLOCKBYTES);
-+ }
-+@@ -221,7 +221,7 @@ static void blake2b_compress(blake2b_state *S, const uint8_t *block) {
-+ #undef ROUND
-+ }
-+
-+-int blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
-++int blake2b_update_wowseed(blake2b_state *S, const void *in, size_t inlen) {
-+ const uint8_t *pin = (const uint8_t *)in;
-+
-+ if (inlen == 0) {
-+@@ -261,7 +261,7 @@ int blake2b_update(blake2b_state *S, const void *in, size_t inlen) {
-+ return 0;
-+ }
-+
-+-int blake2b_final(blake2b_state *S, void *out, size_t outlen) {
-++int blake2b_final_wowseed(blake2b_state *S, void *out, size_t outlen) {
-+ uint8_t buffer[BLAKE2B_OUTBYTES] = {0};
-+ unsigned int i;
-+
-+@@ -291,7 +291,7 @@ int blake2b_final(blake2b_state *S, void *out, size_t outlen) {
-+ return 0;
-+ }
-+
-+-int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
-++int blake2b_wowseed(void *out, size_t outlen, const void *in, size_t inlen,
-+ const void *key, size_t keylen) {
-+ blake2b_state S;
-+ int ret = -1;
-+@@ -310,19 +310,19 @@ int blake2b(void *out, size_t outlen, const void *in, size_t inlen,
-+ }
-+
-+ if (keylen > 0) {
-+- if (blake2b_init_key(&S, outlen, key, keylen) < 0) {
-++ if (blake2b_init_key_wowseed(&S, outlen, key, keylen) < 0) {
-+ goto fail;
-+ }
-+ } else {
-+- if (blake2b_init(&S, outlen) < 0) {
-++ if (blake2b_init_wowseed(&S, outlen) < 0) {
-+ goto fail;
-+ }
-+ }
-+
-+- if (blake2b_update(&S, in, inlen) < 0) {
-++ if (blake2b_update_wowseed(&S, in, inlen) < 0) {
-+ goto fail;
-+ }
-+- ret = blake2b_final(&S, out, outlen);
-++ ret = blake2b_final_wowseed(&S, out, outlen);
-+
-+ fail:
-+ clear_internal_memory(&S, sizeof(S));
-+@@ -352,25 +352,25 @@ int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) {
-+ } while ((void)0, 0)
-+
-+ if (outlen <= BLAKE2B_OUTBYTES) {
-+- TRY(blake2b_init(&blake_state, outlen));
-+- TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
-+- TRY(blake2b_update(&blake_state, in, inlen));
-+- TRY(blake2b_final(&blake_state, out, outlen));
-++ TRY(blake2b_init_wowseed(&blake_state, outlen));
-++ TRY(blake2b_update_wowseed(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
-++ TRY(blake2b_update_wowseed(&blake_state, in, inlen));
-++ TRY(blake2b_final_wowseed(&blake_state, out, outlen));
-+ } else {
-+ uint32_t toproduce;
-+ uint8_t out_buffer[BLAKE2B_OUTBYTES];
-+ uint8_t in_buffer[BLAKE2B_OUTBYTES];
-+- TRY(blake2b_init(&blake_state, BLAKE2B_OUTBYTES));
-+- TRY(blake2b_update(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
-+- TRY(blake2b_update(&blake_state, in, inlen));
-+- TRY(blake2b_final(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
-++ TRY(blake2b_init_wowseed(&blake_state, BLAKE2B_OUTBYTES));
-++ TRY(blake2b_update_wowseed(&blake_state, outlen_bytes, sizeof(outlen_bytes)));
-++ TRY(blake2b_update_wowseed(&blake_state, in, inlen));
-++ TRY(blake2b_final_wowseed(&blake_state, out_buffer, BLAKE2B_OUTBYTES));
-+ memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
-+ out += BLAKE2B_OUTBYTES / 2;
-+ toproduce = (uint32_t)outlen - BLAKE2B_OUTBYTES / 2;
-+
-+ while (toproduce > BLAKE2B_OUTBYTES) {
-+ memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
-+- TRY(blake2b(out_buffer, BLAKE2B_OUTBYTES, in_buffer,
-++ TRY(blake2b_wowseed(out_buffer, BLAKE2B_OUTBYTES, in_buffer,
-+ BLAKE2B_OUTBYTES, NULL, 0));
-+ memcpy(out, out_buffer, BLAKE2B_OUTBYTES / 2);
-+ out += BLAKE2B_OUTBYTES / 2;
-+@@ -378,7 +378,7 @@ int blake2b_long(void *pout, size_t outlen, const void *in, size_t inlen) {
-+ }
-+
-+ memcpy(in_buffer, out_buffer, BLAKE2B_OUTBYTES);
-+- TRY(blake2b(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
-++ TRY(blake2b_wowseed(out_buffer, toproduce, in_buffer, BLAKE2B_OUTBYTES, NULL,
-+ 0));
-+ memcpy(out, out_buffer, toproduce);
-+ }
-+diff --git a/src/argon2/core.c b/src/argon2/core.c
-+index 5eafe08..c25eb53 100644
-+--- a/src/argon2/core.c
-++++ b/src/argon2/core.c
-+@@ -151,7 +151,7 @@ void clear_internal_memory(void *v, size_t n) {
-+ }
-+ }
-+
-+-void finalize(const argon2_context *context, argon2_instance_t *instance) {
-++void finalize_wowseed(const argon2_context *context, argon2_instance_t *instance) {
-+ if (context != NULL && instance != NULL) {
-+ block blockhash;
-+ uint32_t l;
-+@@ -256,7 +256,7 @@ uint32_t index_alpha(const argon2_instance_t *instance,
-+ }
-+
-+ /* Single-threaded version for p=1 case */
-+-static int fill_memory_blocks_st(argon2_instance_t *instance) {
-++static int _fill_memory_blocks_wowseed_st(argon2_instance_t *instance) {
-+ uint32_t r, s, l;
-+
-+ for (r = 0; r < instance->passes; ++r) {
-+@@ -273,14 +273,14 @@ static int fill_memory_blocks_st(argon2_instance_t *instance) {
-+ return ARGON2_OK;
-+ }
-+
-+-int fill_memory_blocks(argon2_instance_t *instance) {
-++int _fill_memory_blocks_wowseed(argon2_instance_t *instance) {
-+ if (instance == NULL || instance->lanes == 0) {
-+ return ARGON2_INCORRECT_PARAMETER;
-+ }
-+- return fill_memory_blocks_st(instance);
-++ return _fill_memory_blocks_wowseed_st(instance);
-+ }
-+
-+-int validate_inputs(const argon2_context *context) {
-++int validate_inputs_wowseed(const argon2_context *context) {
-+ if (NULL == context) {
-+ return ARGON2_INCORRECT_PARAMETER;
-+ }
-+@@ -407,7 +407,7 @@ int validate_inputs(const argon2_context *context) {
-+ return ARGON2_OK;
-+ }
-+
-+-void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
-++void fill_first_blocks_wowseed(uint8_t *blockhash, const argon2_instance_t *instance) {
-+ uint32_t l;
-+ /* Make the first and second block in each lane as G(H0||0||i) or
-+ G(H0||1||i) */
-+@@ -430,7 +430,7 @@ void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance) {
-+ clear_internal_memory(blockhash_bytes, ARGON2_BLOCK_SIZE);
-+ }
-+
-+-void initial_hash(uint8_t *blockhash, argon2_context *context,
-++void initial_hash_wowseed(uint8_t *blockhash, argon2_context *context,
-+ argon2_type type) {
-+ blake2b_state BlakeHash;
-+ uint8_t value[sizeof(uint32_t)];
-+@@ -439,31 +439,31 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
-+ return;
-+ }
-+
-+- blake2b_init(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH);
-++ blake2b_init_wowseed(&BlakeHash, ARGON2_PREHASH_DIGEST_LENGTH);
-+
-+ store32(&value, context->lanes);
-+- blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-+
-+ store32(&value, context->outlen);
-+- blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-+
-+ store32(&value, context->m_cost);
-+- blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-+
-+ store32(&value, context->t_cost);
-+- blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-+
-+ store32(&value, context->version);
-+- blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-+
-+ store32(&value, (uint32_t)type);
-+- blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-+
-+ store32(&value, context->pwdlen);
-+- blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-+
-+ if (context->pwd != NULL) {
-+- blake2b_update(&BlakeHash, (const uint8_t *)context->pwd,
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)context->pwd,
-+ context->pwdlen);
-+
-+ if (context->flags & ARGON2_FLAG_CLEAR_PASSWORD) {
-+@@ -473,18 +473,18 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
-+ }
-+
-+ store32(&value, context->saltlen);
-+- blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-+
-+ if (context->salt != NULL) {
-+- blake2b_update(&BlakeHash, (const uint8_t *)context->salt,
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)context->salt,
-+ context->saltlen);
-+ }
-+
-+ store32(&value, context->secretlen);
-+- blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-+
-+ if (context->secret != NULL) {
-+- blake2b_update(&BlakeHash, (const uint8_t *)context->secret,
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)context->secret,
-+ context->secretlen);
-+
-+ if (context->flags & ARGON2_FLAG_CLEAR_SECRET) {
-+@@ -494,17 +494,17 @@ void initial_hash(uint8_t *blockhash, argon2_context *context,
-+ }
-+
-+ store32(&value, context->adlen);
-+- blake2b_update(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)&value, sizeof(value));
-+
-+ if (context->ad != NULL) {
-+- blake2b_update(&BlakeHash, (const uint8_t *)context->ad,
-++ blake2b_update_wowseed(&BlakeHash, (const uint8_t *)context->ad,
-+ context->adlen);
-+ }
-+
-+- blake2b_final(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
-++ blake2b_final_wowseed(&BlakeHash, blockhash, ARGON2_PREHASH_DIGEST_LENGTH);
-+ }
-+
-+-int initialize(argon2_instance_t *instance, argon2_context *context) {
-++int initialize_wowseed(argon2_instance_t *instance, argon2_context *context) {
-+ uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH];
-+ int result = ARGON2_OK;
-+
-+@@ -523,7 +523,7 @@ int initialize(argon2_instance_t *instance, argon2_context *context) {
-+ /* H_0 + 8 extra bytes to produce the first blocks */
-+ /* uint8_t blockhash[ARGON2_PREHASH_SEED_LENGTH]; */
-+ /* Hashing all inputs */
-+- initial_hash(blockhash, context, instance->type);
-++ initial_hash_wowseed(blockhash, context, instance->type);
-+ /* Zeroing 8 extra bytes */
-+ clear_internal_memory(blockhash + ARGON2_PREHASH_DIGEST_LENGTH,
-+ ARGON2_PREHASH_SEED_LENGTH -
-+@@ -535,7 +535,7 @@ int initialize(argon2_instance_t *instance, argon2_context *context) {
-+
-+ /* 3. Creating first blocks, we always have at least two blocks in a slice
-+ */
-+- fill_first_blocks(blockhash, instance);
-++ fill_first_blocks_wowseed(blockhash, instance);
-+ /* Clearing the hash */
-+ clear_internal_memory(blockhash, ARGON2_PREHASH_SEED_LENGTH);
-+
-+diff --git a/src/argon2/core.h b/src/argon2/core.h
-+index 78000ba..6b0154c 100644
-+--- a/src/argon2/core.h
-++++ b/src/argon2/core.h
-+@@ -53,7 +53,7 @@ typedef struct block_ { uint64_t v[ARGON2_QWORDS_IN_BLOCK]; } block;
-+
-+ /*****************Functions that work with the block******************/
-+
-+-/* Initialize each byte of the block with @in */
-++/* initialize_wowseed each byte of the block with @in */
-+ void init_block_value(block *b, uint8_t in);
-+
-+ /* Copy block @src to block @dst */
-+@@ -158,7 +158,7 @@ uint32_t index_alpha(const argon2_instance_t *instance,
-+ * @return ARGON2_OK if everything is all right, otherwise one of error codes
-+ * (all defined in <argon2.h>
-+ */
-+-int validate_inputs(const argon2_context *context);
-++int validate_inputs_wowseed(const argon2_context *context);
-+
-+ /*
-+ * Hashes all the inputs into @a blockhash[PREHASH_DIGEST_LENGTH], clears
-+@@ -170,28 +170,27 @@ int validate_inputs(const argon2_context *context);
-+ * @pre @a blockhash must have at least @a PREHASH_DIGEST_LENGTH bytes
-+ * allocated
-+ */
-+-void initial_hash(uint8_t *blockhash, argon2_context *context,
-++void initial_hash_wowseed(uint8_t *blockhash, argon2_context *context,
-+ argon2_type type);
-+-
-+ /*
-+ * Function creates first 2 blocks per lane
-+ * @param instance Pointer to the current instance
-+ * @param blockhash Pointer to the pre-hashing digest
-+ * @pre blockhash must point to @a PREHASH_SEED_LENGTH allocated values
-+ */
-+-void fill_first_blocks(uint8_t *blockhash, const argon2_instance_t *instance);
-++void fill_first_blocks_wowseed(uint8_t *blockhash, const argon2_instance_t *instance);
-+
-+ /*
-+ * Function allocates memory, hashes the inputs with Blake, and creates first
-+ * two blocks. Returns the pointer to the main memory with 2 blocks per lane
-+- * initialized
-++ * initialize_wowseedd
-+ * @param context Pointer to the Argon2 internal structure containing memory
-+ * pointer, and parameters for time and space requirements.
-+ * @param instance Current Argon2 instance
-+ * @return Zero if successful, -1 if memory failed to allocate. @context->state
-+ * will be modified if successful.
-+ */
-+-int initialize(argon2_instance_t *instance, argon2_context *context);
-++int initialize_wowseed(argon2_instance_t *instance, argon2_context *context);
-+
-+ /*
-+ * XORing the last block of each lane, hashing it, making the tag. Deallocates
-+@@ -204,7 +203,7 @@ int initialize(argon2_instance_t *instance, argon2_context *context);
-+ * @pre if context->free_cbk is not NULL, it should point to a function that
-+ * deallocates memory
-+ */
-+-void finalize(const argon2_context *context, argon2_instance_t *instance);
-++void finalize_wowseed(const argon2_context *context, argon2_instance_t *instance);
-+
-+ /*
-+ * Function that fills the segment using previous segments also from other
-+@@ -223,6 +222,6 @@ void fill_segment(const argon2_instance_t *instance,
-+ * @param instance Pointer to the current instance
-+ * @return ARGON2_OK if successful, @context->state
-+ */
-+-int fill_memory_blocks(argon2_instance_t *instance);
-++int _fill_memory_blocks_wowseed(argon2_instance_t *instance);
-+
-+ #endif
-+diff --git a/src/argon2/ref.c b/src/argon2/ref.c
-+index ad1cf46..7edbd6e 100644
-+--- a/src/argon2/ref.c
-++++ b/src/argon2/ref.c
-+@@ -29,7 +29,7 @@
-+
-+ /*
-+ * Function fills a new memory block and optionally XORs the old block over the new one.
-+- * @next_block must be initialized.
-++ * @next_block must be initialize_wowseedd.
-+ * @param prev_block Pointer to the previous block
-+ * @param ref_block Pointer to the reference block
-+ * @param next_block Pointer to the block to be constructed
-+--
-+2.39.2
---
-2.45.2
-
diff --git a/patches/monero/0004-coin-control.patch b/patches/wownero/0010-coin-control.patch
index 1700a61..2362fed 100644
--- a/patches/monero/0004-coin-control.patch
+++ b/patches/wownero/0010-coin-control.patch
@@ -1,25 +1,39 @@
-From d6d52b6156f1e83a69474a871043d414e4488f62 Mon Sep 17 00:00:00 2001
+From 14bcfd4bb49e7697c034d3d38c988f90a1842145 Mon Sep 17 00:00:00 2001
From: tobtoht <tob@featherwallet.org>
Date: Tue, 12 Mar 2024 11:07:57 +0100
-Subject: [PATCH 04/16] coin control
+Subject: [PATCH 10/15] coin control
---
- src/wallet/api/CMakeLists.txt | 8 +-
- src/wallet/api/coins.cpp | 185 ++++++++++++++++++++++++++++++++++
- src/wallet/api/coins.h | 40 ++++++++
- src/wallet/api/coins_info.cpp | 122 ++++++++++++++++++++++
- src/wallet/api/coins_info.h | 71 +++++++++++++
- src/wallet/api/wallet.cpp | 26 ++++-
- src/wallet/api/wallet.h | 10 +-
- src/wallet/api/wallet2_api.h | 52 +++++++++-
- src/wallet/wallet2.cpp | 46 ++++++++-
- src/wallet/wallet2.h | 11 +-
- 10 files changed, 555 insertions(+), 16 deletions(-)
+ src/simplewallet/simplewallet.cpp | 2 +-
+ src/wallet/api/CMakeLists.txt | 8 +-
+ src/wallet/api/coins.cpp | 186 ++++++++++++++++++++++++++++++
+ src/wallet/api/coins.h | 40 +++++++
+ src/wallet/api/coins_info.cpp | 122 ++++++++++++++++++++
+ src/wallet/api/coins_info.h | 71 ++++++++++++
+ src/wallet/api/wallet.cpp | 64 +++++++++-
+ src/wallet/api/wallet.h | 10 +-
+ src/wallet/api/wallet2_api.h | 52 ++++++++-
+ src/wallet/wallet2.cpp | 46 +++++++-
+ src/wallet/wallet2.h | 11 +-
+ 11 files changed, 593 insertions(+), 19 deletions(-)
create mode 100644 src/wallet/api/coins.cpp
create mode 100644 src/wallet/api/coins.h
create mode 100644 src/wallet/api/coins_info.cpp
create mode 100644 src/wallet/api/coins_info.h
+diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
+index 8c5122097..cfdb8935f 100644
+--- a/src/simplewallet/simplewallet.cpp
++++ b/src/simplewallet/simplewallet.cpp
+@@ -6981,7 +6981,7 @@ bool simple_wallet::transfer_main(const std::vector<std::string> &args_, bool ca
+ {
+ // figure out what tx will be necessary
+ auto ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, priority, extra,
+- m_current_subaddress_account, subaddr_indices, subtract_fee_from_outputs);
++ m_current_subaddress_account, subaddr_indices, {}, subtract_fee_from_outputs);
+
+ if (ptx_vector.empty())
+ {
diff --git a/src/wallet/api/CMakeLists.txt b/src/wallet/api/CMakeLists.txt
index af7948d8a..bb740e2ac 100644
--- a/src/wallet/api/CMakeLists.txt
@@ -48,10 +62,10 @@ index af7948d8a..bb740e2ac 100644
${wallet_api_private_headers})
diff --git a/src/wallet/api/coins.cpp b/src/wallet/api/coins.cpp
new file mode 100644
-index 000000000..2321c638d
+index 000000000..ef12141cf
--- /dev/null
+++ b/src/wallet/api/coins.cpp
-@@ -0,0 +1,185 @@
+@@ -0,0 +1,186 @@
+#include "coins.h"
+#include "coins_info.h"
+#include "wallet.h"
@@ -168,6 +182,7 @@ index 000000000..2321c638d
+{
+ try
+ {
++ LOG_ERROR("Freezing coin: " << index);
+ m_wallet->m_wallet->freeze(index);
+ refresh();
+ }
@@ -489,7 +504,7 @@ index 000000000..c43e45abd
+
+#endif //FEATHER_COINS_INFO_H
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index 837b98e6b..2106dbd07 100644
+index 704e5e148..e69910e69 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
@@ -35,6 +35,7 @@
@@ -500,15 +515,15 @@ index 837b98e6b..2106dbd07 100644
#include "subaddress_account.h"
#include "common_defines.h"
#include "common/util.h"
-@@ -469,6 +470,7 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds)
- m_refreshEnabled = false;
+@@ -473,6 +474,7 @@ WalletImpl::WalletImpl(NetworkType nettype, uint64_t kdf_rounds)
+ m_wallet->set_refresh_enabled(false);
m_addressBook.reset(new AddressBookImpl(this));
m_subaddress.reset(new SubaddressImpl(this));
+ m_coins.reset(new CoinsImpl(this));
m_subaddressAccount.reset(new SubaddressAccountImpl(this));
-@@ -1752,7 +1754,7 @@ PendingTransaction* WalletImpl::restoreMultisigTransaction(const string& signDat
+@@ -2046,7 +2048,7 @@ PendingTransaction* WalletImpl::restoreMultisigTransaction(const string& signDat
// - unconfirmed_transfer_details;
// - confirmed_transfer_details)
@@ -517,27 +532,89 @@ index 837b98e6b..2106dbd07 100644
{
clearStatus();
-@@ -1821,6 +1823,19 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
+@@ -2084,6 +2086,7 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
+ }
+ }
+ bool error = false;
++ uint64_t amountSum = 0;
+ for (size_t i = 0; i < dst_addr.size() && !error; i++) {
+ if(!cryptonote::get_account_address_from_str(info, m_wallet->nettype(), dst_addr[i])) {
+ // TODO: copy-paste 'if treating as an address fails, try as url' from simplewallet.cpp:1982
+@@ -2105,6 +2108,7 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
+ de.original = dst_addr[i];
+ de.addr = info.address;
+ de.amount = (*amount)[i];
++ amountSum += (*amount)[i];
+ de.is_subaddress = info.is_subaddress;
+ de.is_integrated = info.has_payment_id;
+ dsts.push_back(de);
+@@ -2115,6 +2119,51 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
}
}
}
++ // uint64_t maxAllowedSpend = m_wallet->unlocked_balance(subaddr_account, true);
++ // if (maxAllowedSpend < amountSum) {
++ // error = true;
++ // setStatusError(tr("Amount you are trying to spend is larger than unlocked amount"));
++ // break;
++ // }
+ std::vector<crypto::key_image> preferred_input_list;
+ if (!preferred_inputs.empty()) {
++ LOG_ERROR("empty");
++
+ for (const auto &public_key : preferred_inputs) {
+ crypto::key_image keyImage;
+ bool r = epee::string_tools::hex_to_pod(public_key, keyImage);
-+ if (!r) {
++ if (!r) {
+ error = true;
+ setStatusError(tr("failed to parse key image"));
+ break;
+ }
++ if (m_wallet->frozen(keyImage)) {
++ error = true;
++ setStatusError(tr("refusing to spend frozen coin"));
++ break;
++ }
++
+ preferred_input_list.push_back(keyImage);
+ }
++ } else {
++ LOG_ERROR("not empty");
++
++ boost::shared_lock<boost::shared_mutex> transfers_lock(m_wallet->m_transfers_mutex);
++ for (size_t i = 0; i < m_wallet->get_num_transfer_details(); ++i) {
++ const tools::wallet2::transfer_details &td = m_wallet->get_transfer_details(i);
++ LOG_ERROR("COIN: " << i << ": " << td.amount() << "; "<<td.m_spent << ";" << td.m_frozen << ";" << m_wallet->frozen(td));
++ if (td.m_spent) continue;
++ LOG_ERROR("is frozen");
++ if (!td.m_frozen) {
++ LOG_ERROR("isn't:");
++ LOG_ERROR("hash: " << td.m_key_image << "; " << td.amount());
++ preferred_input_list.push_back(td.m_key_image);
++ }
++ }
++ }
++ for (const auto &de : preferred_input_list) {
++ LOG_ERROR("preferred input: " << de);
+ }
if (error) {
break;
}
-@@ -1920,10 +1935,10 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
+@@ -2129,11 +2178,11 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
+ if (amount) {
+ transaction->m_pending_tx = m_wallet->create_transactions_2(dsts, fake_outs_count,
+ adjusted_priority,
+- extra, subaddr_account, subaddr_indices);
++ extra, subaddr_account, subaddr_indices, preferred_input_list);
+ } else {
+ transaction->m_pending_tx = m_wallet->create_transactions_all(0, info.address, info.is_subaddress, 1, fake_outs_count,
+ adjusted_priority,
+- extra, subaddr_account, subaddr_indices);
++ extra, subaddr_account, subaddr_indices, preferred_input_list);
+ }
+ pendingTxPostProcess(transaction);
+
+@@ -2214,10 +2263,10 @@ PendingTransaction *WalletImpl::createTransactionMultDest(const std::vector<stri
}
PendingTransaction *WalletImpl::createTransaction(const string &dst_addr, const string &payment_id, optional<uint64_t> amount, uint32_t mixin_count,
@@ -550,7 +627,7 @@ index 837b98e6b..2106dbd07 100644
}
PendingTransaction *WalletImpl::createSweepUnmixableTransaction()
-@@ -2048,6 +2063,11 @@ AddressBook *WalletImpl::addressBook()
+@@ -2342,6 +2391,11 @@ AddressBook *WalletImpl::addressBook()
return m_addressBook.get();
}
@@ -563,7 +640,7 @@ index 837b98e6b..2106dbd07 100644
{
return m_subaddress.get();
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
-index 05d065c5c..4a16ca028 100644
+index 32e12284b..a82f270e4 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -46,6 +46,7 @@ class PendingTransactionImpl;
@@ -590,8 +667,8 @@ index 05d065c5c..4a16ca028 100644
+ const std::set<std::string> &preferred_inputs = {}) override;
virtual PendingTransaction * createSweepUnmixableTransaction() override;
bool submitTransaction(const std::string &fileName) override;
- virtual UnsignedTransaction * loadUnsignedTx(const std::string &unsigned_filename) override;
-@@ -195,6 +198,7 @@ public:
+ bool submitTransactionUR(const std::string &input) override;
+@@ -201,6 +204,7 @@ public:
PendingTransaction::Priority priority) const override;
virtual TransactionHistory * history() override;
virtual AddressBook * addressBook() override;
@@ -599,7 +676,7 @@ index 05d065c5c..4a16ca028 100644
virtual Subaddress * subaddress() override;
virtual SubaddressAccount * subaddressAccount() override;
virtual void setListener(WalletListener * l) override;
-@@ -266,6 +270,7 @@ private:
+@@ -272,6 +276,7 @@ private:
friend class TransactionHistoryImpl;
friend struct Wallet2CallbackImpl;
friend class AddressBookImpl;
@@ -607,7 +684,7 @@ index 05d065c5c..4a16ca028 100644
friend class SubaddressImpl;
friend class SubaddressAccountImpl;
-@@ -282,6 +287,7 @@ private:
+@@ -288,6 +293,7 @@ private:
std::unique_ptr<Wallet2CallbackImpl> m_wallet2Callback;
std::unique_ptr<AddressBookImpl> m_addressBook;
std::unique_ptr<SubaddressImpl> m_subaddress;
@@ -616,10 +693,10 @@ index 05d065c5c..4a16ca028 100644
// multi-threaded refresh stuff
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
-index 4edaefefd..8a5c4135e 100644
+index be1c3704e..013b5bcba 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
-@@ -261,6 +261,51 @@ struct AddressBook
+@@ -263,6 +263,51 @@ struct AddressBook
virtual int lookupPaymentID(const std::string &payment_id) const = 0;
};
@@ -671,7 +748,7 @@ index 4edaefefd..8a5c4135e 100644
struct SubaddressRow {
public:
SubaddressRow(std::size_t _rowId, const std::string &_address, const std::string &_label):
-@@ -854,7 +899,8 @@ struct Wallet
+@@ -856,7 +901,8 @@ struct Wallet
optional<std::vector<uint64_t>> amount, uint32_t mixin_count,
PendingTransaction::Priority = PendingTransaction::Priority_Low,
uint32_t subaddr_account = 0,
@@ -681,7 +758,7 @@ index 4edaefefd..8a5c4135e 100644
/*!
* \brief createTransaction creates transaction. if dst_addr is an integrated address, payment_id is ignored
-@@ -873,7 +919,8 @@ struct Wallet
+@@ -875,7 +921,8 @@ struct Wallet
optional<uint64_t> amount, uint32_t mixin_count,
PendingTransaction::Priority = PendingTransaction::Priority_Low,
uint32_t subaddr_account = 0,
@@ -691,7 +768,7 @@ index 4edaefefd..8a5c4135e 100644
/*!
* \brief createSweepUnmixableTransaction creates transaction with unmixable outputs.
-@@ -987,6 +1034,7 @@ struct Wallet
+@@ -994,6 +1041,7 @@ struct Wallet
virtual TransactionHistory * history() = 0;
virtual AddressBook * addressBook() = 0;
@@ -700,10 +777,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 41cf1fd41..61601f70c 100644
+index 3e49c21f8..4d756567f 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
-@@ -2083,12 +2083,21 @@ bool wallet2::frozen(const multisig_tx_set& txs) const
+@@ -2094,12 +2094,21 @@ bool wallet2::frozen(const multisig_tx_set& txs) const
return false;
}
@@ -725,7 +802,7 @@ index 41cf1fd41..61601f70c 100644
void wallet2::thaw(const crypto::key_image &ki)
{
thaw(get_transfer_details(ki));
-@@ -2099,6 +2108,18 @@ bool wallet2::frozen(const crypto::key_image &ki) const
+@@ -2110,6 +2119,18 @@ bool wallet2::frozen(const crypto::key_image &ki) const
return frozen(get_transfer_details(ki));
}
//----------------------------------------------------------------------------------------------------
@@ -744,7 +821,7 @@ index 41cf1fd41..61601f70c 100644
size_t wallet2::get_transfer_details(const crypto::key_image &ki) const
{
for (size_t idx = 0; idx < m_transfers.size(); ++idx)
-@@ -2510,6 +2531,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+@@ -2523,6 +2544,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)
{
@@ -752,7 +829,7 @@ index 41cf1fd41..61601f70c 100644
m_transfers.push_back(transfer_details{});
transfer_details& td = m_transfers.back();
td.m_block_height = height;
-@@ -2613,6 +2635,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
+@@ -2626,6 +2648,7 @@ void wallet2::process_new_transaction(const crypto::hash &txid, const cryptonote
uint64_t extra_amount = amount - burnt;
if (!pool)
{
@@ -760,7 +837,7 @@ index 41cf1fd41..61601f70c 100644
transfer_details &td = m_transfers[kit->second];
td.m_block_height = height;
td.m_internal_output_index = o;
-@@ -10487,7 +10510,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
+@@ -10497,7 +10520,7 @@ void wallet2::transfer_selected_rct(std::vector<cryptonote::tx_destination_entry
LOG_PRINT_L2("transfer_selected_rct done");
}
@@ -769,7 +846,7 @@ index 41cf1fd41..61601f70c 100644
{
std::vector<size_t> picks;
float current_output_relatdness = 1.0f;
-@@ -10498,6 +10521,9 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
+@@ -10508,6 +10531,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];
@@ -779,7 +856,7 @@ index 41cf1fd41..61601f70c 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)
-@@ -10518,6 +10544,9 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
+@@ -10528,6 +10554,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];
@@ -789,7 +866,7 @@ index 41cf1fd41..61601f70c 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)
-@@ -10529,6 +10558,9 @@ std::vector<size_t> wallet2::pick_preferred_rct_inputs(uint64_t needed_money, ui
+@@ -10539,6 +10568,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];
@@ -799,7 +876,7 @@ index 41cf1fd41..61601f70c 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) << "]");
-@@ -11101,7 +11133,7 @@ bool wallet2::light_wallet_key_image_is_ours(const crypto::key_image& key_image,
+@@ -11111,7 +11143,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.
@@ -808,7 +885,7 @@ index 41cf1fd41..61601f70c 100644
{
//ensure device is let in NONE mode in any case
hw::device &hwdev = m_account.get_device();
-@@ -11309,6 +11341,9 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
+@@ -11319,6 +11351,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];
@@ -818,7 +895,7 @@ index 41cf1fd41..61601f70c 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));
-@@ -11400,7 +11435,7 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_2(std::vector<cryp
+@@ -11410,7 +11445,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);
@@ -827,7 +904,7 @@ index 41cf1fd41..61601f70c 100644
if (!preferred_inputs.empty())
{
string s;
-@@ -11879,7 +11914,7 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, c
+@@ -11889,7 +11924,7 @@ bool wallet2::sanity_check(const std::vector<wallet2::pending_tx> &ptx_vector, c
return true;
}
@@ -836,7 +913,7 @@ index 41cf1fd41..61601f70c 100644
{
std::vector<size_t> unused_transfers_indices;
std::vector<size_t> unused_dust_indices;
-@@ -11908,6 +11943,9 @@ std::vector<wallet2::pending_tx> wallet2::create_transactions_all(uint64_t below
+@@ -11918,6 +11953,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];
@@ -847,21 +924,21 @@ index 41cf1fd41..61601f70c 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 b9aa7a00d..67ed81383 100644
+index c26349ce3..a48ba33b6 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
-@@ -1207,8 +1207,8 @@ private:
+@@ -1209,8 +1209,8 @@ private:
bool parse_unsigned_tx_from_str(const std::string &unsigned_tx_st, unsigned_tx_set &exported_txs) const;
bool load_tx(const std::string &signed_filename, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set&)> accept_func = NULL);
bool parse_tx_from_str(const std::string &signed_tx_st, std::vector<tools::wallet2::pending_tx> &ptx, std::function<bool(const signed_tx_set &)> accept_func);
- std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const unique_index_container& subtract_fee_from_outputs = {}); // pass subaddr_indices by value on purpose
- std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices);
-+ std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list, const unique_index_container& subtract_fee_from_outputs = {}); // pass subaddr_indices by value on purpose
++ std::vector<wallet2::pending_tx> create_transactions_2(std::vector<cryptonote::tx_destination_entry> dsts, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list = {}, const unique_index_container& subtract_fee_from_outputs = {}); // pass subaddr_indices by value on purpose
+ std::vector<wallet2::pending_tx> create_transactions_all(uint64_t below, const cryptonote::account_public_address &address, bool is_subaddress, const size_t outputs, const size_t fake_outs_count, uint32_t priority, const std::vector<uint8_t>& extra, uint32_t subaddr_account, std::set<uint32_t> subaddr_indices, const std::vector<crypto::key_image>& preferred_input_list = {});
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, 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, 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;
-@@ -1560,6 +1560,7 @@ private:
+@@ -1562,6 +1562,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;
@@ -869,7 +946,7 @@ index b9aa7a00d..67ed81383 100644
uint8_t get_current_hard_fork();
void get_hard_fork_info(uint8_t version, uint64_t &earliest_height);
-@@ -1789,7 +1790,9 @@ private:
+@@ -1793,7 +1794,9 @@ private:
void freeze(size_t idx);
void thaw(size_t idx);
bool frozen(size_t idx) const;
@@ -879,7 +956,7 @@ index b9aa7a00d..67ed81383 100644
void thaw(const crypto::key_image &ki);
bool frozen(const crypto::key_image &ki) const;
bool frozen(const transfer_details &td) const;
-@@ -1830,6 +1833,8 @@ private:
+@@ -1834,6 +1837,8 @@ private:
static std::string get_default_daemon_address() { CRITICAL_REGION_LOCAL(default_daemon_address_lock); return default_daemon_address; }
@@ -888,7 +965,7 @@ index b9aa7a00d..67ed81383 100644
private:
/*!
* \brief Stores wallet information to wallet file.
-@@ -1901,7 +1906,7 @@ private:
+@@ -1905,7 +1910,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;
@@ -898,5 +975,5 @@ index b9aa7a00d..67ed81383 100644
void set_unspent(size_t idx);
bool is_spent(const transfer_details &td, bool strict = true) const;
--
-2.39.2
+2.39.5 (Apple Git-154)
diff --git a/patches/wownero/0011-Add-hex-encoding-and-tx-key-getter-for-PendingTransc.patch b/patches/wownero/0011-Add-hex-encoding-and-tx-key-getter-for-PendingTransc.patch
new file mode 100644
index 0000000..f130f51
--- /dev/null
+++ b/patches/wownero/0011-Add-hex-encoding-and-tx-key-getter-for-PendingTransc.patch
@@ -0,0 +1,68 @@
+From 7c4f0b36d627bf4d1ce198240c1e974eff27bbec Mon Sep 17 00:00:00 2001
+From: M <m@cakewallet.com>
+Date: Fri, 21 Apr 2023 15:43:47 -0400
+Subject: [PATCH 11/15] Add hex encoding and tx key getter for
+ PendingTransction in wallet api.
+
+---
+ src/wallet/api/pending_transaction.cpp | 16 ++++++++++++++++
+ src/wallet/api/pending_transaction.h | 2 ++
+ src/wallet/api/wallet2_api.h | 2 ++
+ 3 files changed, 20 insertions(+)
+
+diff --git a/src/wallet/api/pending_transaction.cpp b/src/wallet/api/pending_transaction.cpp
+index 9c3c26ee5..1f714d229 100644
+--- a/src/wallet/api/pending_transaction.cpp
++++ b/src/wallet/api/pending_transaction.cpp
+@@ -80,6 +80,22 @@ std::vector<std::string> PendingTransactionImpl::txid() const
+ return txid;
+ }
+
++std::vector<std::string> PendingTransactionImpl::hex() const
++{
++ std::vector<std::string> hexs;
++ for (const auto &pt: m_pending_tx)
++ hexs.push_back(epee::string_tools::buff_to_hex_nodelimer(cryptonote::tx_to_blob(pt.tx)));
++ return hexs;
++}
++
++std::vector<std::string> PendingTransactionImpl::txKey() const
++{
++ std::vector<std::string> keys;
++ for (const auto& pt: m_pending_tx)
++ keys.push_back(epee::string_tools::pod_to_hex(pt.tx_key));
++ return keys;
++}
++
+ bool PendingTransactionImpl::commit(const std::string &filename, bool overwrite)
+ {
+
+diff --git a/src/wallet/api/pending_transaction.h b/src/wallet/api/pending_transaction.h
+index 403bfe281..0cc6c58e9 100644
+--- a/src/wallet/api/pending_transaction.h
++++ b/src/wallet/api/pending_transaction.h
+@@ -59,6 +59,8 @@ public:
+ std::string multisigSignData() override;
+ void signMultisigTx() override;
+ std::vector<std::string> signersKeys() const override;
++ std::vector<std::string> hex() const override;
++ std::vector<std::string> txKey() const override;
+
+ private:
+ friend class WalletImpl;
+diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
+index 013b5bcba..f421fdc05 100644
+--- a/src/wallet/api/wallet2_api.h
++++ b/src/wallet/api/wallet2_api.h
+@@ -127,6 +127,8 @@ struct PendingTransaction
+ * @return vector of base58-encoded signers' public keys
+ */
+ virtual std::vector<std::string> signersKeys() const = 0;
++ virtual std::vector<std::string> hex() const = 0;
++ virtual std::vector<std::string> txKey() const = 0;
+ };
+
+ /**
+--
+2.39.5 (Apple Git-154)
+
diff --git a/patches/wownero/0011-android-ndk-version-bump.patch b/patches/wownero/0011-android-ndk-version-bump.patch
deleted file mode 100644
index 888f00d..0000000
--- a/patches/wownero/0011-android-ndk-version-bump.patch
+++ /dev/null
@@ -1,120 +0,0 @@
-From aff9394b39ccfa9842d47007a644f08b6b370e55 Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Thu, 23 May 2024 08:02:49 +0200
-Subject: [PATCH 11/14] android ndk version bump
-
----
- contrib/depends/hosts/android.mk | 16 +++++++++++++---
- contrib/depends/packages/android_ndk.mk | 20 ++++++++++++++------
- contrib/depends/packages/boost.mk | 1 +
- contrib/depends/toolchain.cmake.in | 11 ++++++-----
- 4 files changed, 34 insertions(+), 14 deletions(-)
-
-diff --git a/contrib/depends/hosts/android.mk b/contrib/depends/hosts/android.mk
-index 5b2309972..c7b6b6d36 100644
---- a/contrib/depends/hosts/android.mk
-+++ b/contrib/depends/hosts/android.mk
-@@ -1,12 +1,22 @@
- ANDROID_API=21
--
-+host_toolchain=nonexistent
- ifeq ($(host_arch),arm)
--host_toolchain=arm-linux-androideabi-
-+host_toolchain=armv7a-linux-androideabi${ANDROID_API}-
-+endif
-+ifeq ($(host_arch),x86_64)
-+host_toolchain=x86_64-linux-android${ANDROID_API}-
-+endif
-+ifeq ($(host_arch),i686)
-+host_toolchain=i686-linux-android${ANDROID_API}-
-+endif
-+ifeq ($(host_arch),aarch64)
-+host_toolchain=aarch64-linux-android${ANDROID_API}-
- endif
-
- android_CC=$(host_toolchain)clang
- android_CXX=$(host_toolchain)clang++
--android_RANLIB=$(host_toolchain)ranlib
-+android_RANLIB=llvm-ranlib
-+android_AR=llvm-ar
- android_AR=$(host_toolchain)ar
-
- android_CFLAGS=-pipe
-diff --git a/contrib/depends/packages/android_ndk.mk b/contrib/depends/packages/android_ndk.mk
-index 5deff76c7..1ad250653 100644
---- a/contrib/depends/packages/android_ndk.mk
-+++ b/contrib/depends/packages/android_ndk.mk
-@@ -1,8 +1,10 @@
- package=android_ndk
--$(package)_version=17b
-+$(package)_version=26d
- $(package)_download_path=https://dl.google.com/android/repository/
--$(package)_file_name=android-ndk-r$($(package)_version)-linux-x86_64.zip
--$(package)_sha256_hash=5dfbbdc2d3ba859fed90d0e978af87c71a91a5be1f6e1c40ba697503d48ccecd
-+$(package)_file_name=android-ndk-r$($(package)_version)-linux.zip
-+$(package)_sha256_hash=eefeafe7ccf177de7cc57158da585e7af119bb7504a63604ad719e4b2a328b54
-+
-+$(package)_version_apiversion=21
-
- define $(package)_set_vars
- $(package)_config_opts_arm=--arch arm
-@@ -17,8 +19,14 @@ define $(package)_extract_cmds
- endef
-
- define $(package)_stage_cmds
-- android-ndk-r$($(package)_version)/build/tools/make_standalone_toolchain.py --api 21 \
-- --install-dir $(build_prefix) --stl=libc++ $($(package)_config_opts) &&\
-- mv $(build_prefix) $($(package)_staging_dir)/$(host_prefix)
-+ mkdir -p $(build_prefix) &&\
-+ echo $(build_prefix)/toolchain && \
-+ android-ndk-r$($(package)_version)/build/tools/make_standalone_toolchain.py --api $($(package)_version_apiversion) \
-+ --install-dir $(build_prefix)/toolchain --stl=libc++ $($(package)_config_opts) &&\
-+ mv $(build_prefix)/toolchain $($(package)_staging_dir)/$(host_prefix)/native && \
-+ cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ar $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)$($(package)_version_apiversion)-ar &&\
-+ cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ranlib $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)$($(package)_version_apiversion)-ranlib &&\
-+ cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ar $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)-ar &&\
-+ cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ranlib $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)-ranlib
- endef
-
-diff --git a/contrib/depends/packages/boost.mk b/contrib/depends/packages/boost.mk
-index fd06c5393..c17e863cc 100644
---- a/contrib/depends/packages/boost.mk
-+++ b/contrib/depends/packages/boost.mk
-@@ -25,6 +25,7 @@ $(package)_archiver_darwin=$($(package)_libtool)
- $(package)_config_libraries=chrono,filesystem,program_options,system,thread,test,date_time,regex,serialization,locale
- $(package)_cxxflags=-std=c++11
- $(package)_cxxflags_linux=-fPIC
-+$(package)_cxxflags_android=-fPIC
- $(package)_cxxflags_freebsd=-fPIC
- endef
-
-diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in
-index f118c754e..249213b20 100644
---- a/contrib/depends/toolchain.cmake.in
-+++ b/contrib/depends/toolchain.cmake.in
-@@ -104,16 +104,17 @@ elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
- SET(CMAKE_ANDROID_ARCH_ABI "armeabi-v7a")
- SET(CMAKE_SYSTEM_PROCESSOR "armv7-a")
- SET(CMAKE_ANDROID_ARM_MODE ON)
-- SET(CMAKE_C_COMPILER_TARGET arm-linux-androideabi)
-- SET(CMAKE_CXX_COMPILER_TARGET arm-linux-androideabi)
-- SET(_CMAKE_TOOLCHAIN_PREFIX arm-linux-androideabi-)
-+ SET(CMAKE_C_COMPILER_TARGET arm-linux-androideabi21)
-+ SET(CMAKE_CXX_COMPILER_TARGET arm-linux-androideabi21)
-+ SET(_CMAKE_TOOLCHAIN_PREFIX arm-linux-androideabi21-)
- elseif(ARCHITECTURE STREQUAL "aarch64")
- SET(CMAKE_ANDROID_ARCH_ABI "arm64-v8a")
- SET(CMAKE_SYSTEM_PROCESSOR "aarch64")
- endif()
- SET(CMAKE_ANDROID_STANDALONE_TOOLCHAIN @prefix@/native)
-- SET(CMAKE_C_COMPILER "${_CMAKE_TOOLCHAIN_PREFIX}clang")
-- SET(CMAKE_CXX_COMPILER "${_CMAKE_TOOLCHAIN_PREFIX}clang++")
-+ SET(_ANDROID_STANDALONE_TOOLCHAIN_API 21)
-+ SET(CMAKE_C_COMPILER @CC@)
-+ SET(CMAKE_CXX_COMPILER @CXX@)
- else()
- SET(CMAKE_C_COMPILER @CC@)
- SET(CMAKE_CXX_COMPILER @CXX@)
---
-2.45.2
-
diff --git a/patches/monero/0009-Add-recoverDeterministicWalletFromSpendKey.patch b/patches/wownero/0012-Add-recoverDeterministicWalletFromSpendKey.patch
index 0ef9900..a15e54c 100644
--- a/patches/monero/0009-Add-recoverDeterministicWalletFromSpendKey.patch
+++ b/patches/wownero/0012-Add-recoverDeterministicWalletFromSpendKey.patch
@@ -1,7 +1,7 @@
-From ff4d7f9500e6aca57a78d94599a70b7823ea6ecd Mon Sep 17 00:00:00 2001
+From 298c7e0745306605d7ed1cee320b92eacf8aaeb6 Mon Sep 17 00:00:00 2001
From: Konstantin Ullrich <konstantinullrich12@gmail.com>
Date: Wed, 11 Oct 2023 16:47:59 +0200
-Subject: [PATCH 09/16] Add recoverDeterministicWalletFromSpendKey
+Subject: [PATCH 12/15] Add recoverDeterministicWalletFromSpendKey
This function is used by Cake Wallet to enable polyseed (dart implementation)
support.
@@ -19,10 +19,10 @@ Co-authored-by: Godwin Asuquo <godilite@gmail.com>
5 files changed, 75 insertions(+)
diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
-index 2106dbd07..ec4ae51ff 100644
+index e69910e69..e650e6044 100644
--- a/src/wallet/api/wallet.cpp
+++ b/src/wallet/api/wallet.cpp
-@@ -820,6 +820,35 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c
+@@ -824,6 +824,35 @@ bool WalletImpl::recover(const std::string &path, const std::string &password, c
return status() == Status_Ok;
}
@@ -59,7 +59,7 @@ index 2106dbd07..ec4ae51ff 100644
{
diff --git a/src/wallet/api/wallet.h b/src/wallet/api/wallet.h
-index 4a16ca028..d0f443abc 100644
+index a82f270e4..9e1fbb40b 100644
--- a/src/wallet/api/wallet.h
+++ b/src/wallet/api/wallet.h
@@ -77,6 +77,10 @@ public:
@@ -74,10 +74,10 @@ index 4a16ca028..d0f443abc 100644
const std::string &password,
const std::string &device_name);
diff --git a/src/wallet/api/wallet2_api.h b/src/wallet/api/wallet2_api.h
-index 8a5c4135e..a585c8212 100644
+index f421fdc05..c8d6bb179 100644
--- a/src/wallet/api/wallet2_api.h
+++ b/src/wallet/api/wallet2_api.h
-@@ -1302,6 +1302,25 @@ struct WalletManager
+@@ -1323,6 +1323,25 @@ struct WalletManager
return createWalletFromKeys(path, password, language, testnet ? TESTNET : MAINNET, restoreHeight, addressString, viewKeyString, spendKeyString);
}
@@ -104,7 +104,7 @@ index 8a5c4135e..a585c8212 100644
* \deprecated this method creates a wallet WITHOUT a passphrase, use createWalletFromKeys(..., password, ...) instead
* \brief recovers existing wallet using keys. Creates a view only wallet if spend key is omitted
diff --git a/src/wallet/api/wallet_manager.cpp b/src/wallet/api/wallet_manager.cpp
-index c79fe25d6..f88bd9e64 100644
+index da2056d8a..c200f52ae 100644
--- a/src/wallet/api/wallet_manager.cpp
+++ b/src/wallet/api/wallet_manager.cpp
@@ -127,6 +127,22 @@ Wallet *WalletManagerImpl::createWalletFromKeys(const std::string &path,
@@ -149,5 +149,5 @@ index 28fcd36c9..be3ff8184 100644
const std::string &password,
NetworkType nettype,
--
-2.39.2
+2.39.5 (Apple Git-154)
diff --git a/patches/wownero/0012-rename-arm-armv7a.patch b/patches/wownero/0012-rename-arm-armv7a.patch
deleted file mode 100644
index 9f6b91f..0000000
--- a/patches/wownero/0012-rename-arm-armv7a.patch
+++ /dev/null
@@ -1,94 +0,0 @@
-From c40118e32ff966d0796b0b8f36f26a6f08dcfa90 Mon Sep 17 00:00:00 2001
-From: Czarek Nakamoto <cyjan@mrcyjanek.net>
-Date: Wed, 12 Jun 2024 15:48:01 +0200
-Subject: [PATCH 12/14] rename arm -> armv7a
-
----
- contrib/depends/hosts/android.mk | 2 +-
- contrib/depends/packages/android_ndk.mk | 6 +++++-
- contrib/depends/packages/openssl.mk | 2 +-
- contrib/depends/toolchain.cmake.in | 8 ++++----
- 4 files changed, 11 insertions(+), 7 deletions(-)
-
-diff --git a/contrib/depends/hosts/android.mk b/contrib/depends/hosts/android.mk
-index c7b6b6d36..9477b4e22 100644
---- a/contrib/depends/hosts/android.mk
-+++ b/contrib/depends/hosts/android.mk
-@@ -1,6 +1,6 @@
- ANDROID_API=21
- host_toolchain=nonexistent
--ifeq ($(host_arch),arm)
-+ifeq ($(host_arch),armv7a)
- host_toolchain=armv7a-linux-androideabi${ANDROID_API}-
- endif
- ifeq ($(host_arch),x86_64)
-diff --git a/contrib/depends/packages/android_ndk.mk b/contrib/depends/packages/android_ndk.mk
-index 1ad250653..2c2914ec2 100644
---- a/contrib/depends/packages/android_ndk.mk
-+++ b/contrib/depends/packages/android_ndk.mk
-@@ -7,7 +7,7 @@ $(package)_sha256_hash=eefeafe7ccf177de7cc57158da585e7af119bb7504a63604ad719e4b2
- $(package)_version_apiversion=21
-
- define $(package)_set_vars
--$(package)_config_opts_arm=--arch arm
-+$(package)_config_opts_armv7a=--arch arm
- $(package)_config_opts_aarch64=--arch arm64
- $(package)_config_opts_x86_64=--arch x86_64
- $(package)_config_opts_i686=--arch x86
-@@ -18,6 +18,8 @@ define $(package)_extract_cmds
- unzip -q $($(1)_source_dir)/$($(package)_file_name)
- endef
-
-+# arm-linux-androideabi-ar - openssl workaround
-+
- define $(package)_stage_cmds
- mkdir -p $(build_prefix) &&\
- echo $(build_prefix)/toolchain && \
-@@ -25,7 +27,9 @@ define $(package)_stage_cmds
- --install-dir $(build_prefix)/toolchain --stl=libc++ $($(package)_config_opts) &&\
- mv $(build_prefix)/toolchain $($(package)_staging_dir)/$(host_prefix)/native && \
- cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ar $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)$($(package)_version_apiversion)-ar &&\
-+ cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ar $($(package)_staging_dir)/$(host_prefix)/native/bin/arm-linux-androideabi-ar &&\
- cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ranlib $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)$($(package)_version_apiversion)-ranlib &&\
-+ cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ranlib $($(package)_staging_dir)/$(host_prefix)/native/bin/arm-linux-androideabi-ranlib &&\
- cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ar $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)-ar &&\
- cp $($(package)_staging_dir)/$(host_prefix)/native/bin/llvm-ranlib $($(package)_staging_dir)/$(host_prefix)/native/bin/$(host)-ranlib
- endef
-diff --git a/contrib/depends/packages/openssl.mk b/contrib/depends/packages/openssl.mk
-index a157762c7..2430f6495 100644
---- a/contrib/depends/packages/openssl.mk
-+++ b/contrib/depends/packages/openssl.mk
-@@ -34,7 +34,7 @@ $(package)_config_opts_x86_64_linux=linux-x86_64
- $(package)_config_opts_i686_linux=linux-generic32
- $(package)_config_opts_arm_linux=linux-generic32
- $(package)_config_opts_aarch64_linux=linux-generic64
--$(package)_config_opts_arm_android=--static android-arm
-+$(package)_config_opts_armv7a_android=--static android-arm
- $(package)_config_opts_aarch64_android=--static android-arm64
- $(package)_config_opts_aarch64_darwin=darwin64-arm64-cc
- $(package)_config_opts_riscv64_linux=linux-generic64
-diff --git a/contrib/depends/toolchain.cmake.in b/contrib/depends/toolchain.cmake.in
-index 249213b20..cc1d9b5c5 100644
---- a/contrib/depends/toolchain.cmake.in
-+++ b/contrib/depends/toolchain.cmake.in
-@@ -100,13 +100,13 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
- SET(LLVM_ENABLE_PIE OFF)
- elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
- SET(ANDROID TRUE)
-- if(ARCHITECTURE STREQUAL "arm")
-+ if(ARCHITECTURE STREQUAL "armv7a")
- SET(CMAKE_ANDROID_ARCH_ABI "armeabi-v7a")
- SET(CMAKE_SYSTEM_PROCESSOR "armv7-a")
- SET(CMAKE_ANDROID_ARM_MODE ON)
-- SET(CMAKE_C_COMPILER_TARGET arm-linux-androideabi21)
-- SET(CMAKE_CXX_COMPILER_TARGET arm-linux-androideabi21)
-- SET(_CMAKE_TOOLCHAIN_PREFIX arm-linux-androideabi21-)
-+ SET(CMAKE_C_COMPILER_TARGET armv7a-linux-androideabi21)
-+ SET(CMAKE_CXX_COMPILER_TARGET armv7a-linux-androideabi21)
-+ SET(_CMAKE_TOOLCHAIN_PREFIX armv7a-linux-androideabi21-)
- elseif(ARCHITECTURE STREQUAL "aarch64")
- SET(CMAKE_ANDROID_ARCH_ABI "arm64-v8a")
- SET(CMAKE_SYSTEM_PROCESSOR "aarch64")
---
-2.45.2
-
diff --git a/patches/wownero/0013-add-monero-submodule-support.patch b/patches/wownero/0013-add-monero-submodule-support.patch
new file mode 100644
index 0000000..f220055
--- /dev/null
+++ b/patches/wownero/0013-add-monero-submodule-support.patch
@@ -0,0 +1,65 @@
+From 1bd61531746e983799fcae9d3a7228620bbc84f5 Mon Sep 17 00:00:00 2001
+From: cyan <cyjan@mrcyjanek.net>
+Date: Thu, 7 Nov 2024 16:46:24 +0000
+Subject: [PATCH 13/15] add monero submodule support
+
+---
+ CMakeLists.txt | 6 +++---
+ cmake/CheckLinkerFlag.cmake | 2 +-
+ src/wallet/wallet_rpc_server.cpp | 2 +-
+ 3 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 85a62ef7b..763d240fc 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -223,9 +223,9 @@ function(forbid_undefined_symbols)
+ cmake_minimum_required(VERSION 3.1)
+ project(test)
+ option(EXPECT_SUCCESS "" ON)
+-file(WRITE "${CMAKE_SOURCE_DIR}/incorrect_source.cpp" "void undefined_symbol(); void symbol() { undefined_symbol(); }")
++file(WRITE "${CMAKE_CURRENT_SOURCE_DIR}/incorrect_source.cpp" "void undefined_symbol(); void symbol() { undefined_symbol(); }")
+ if (EXPECT_SUCCESS)
+- file(APPEND "${CMAKE_SOURCE_DIR}/incorrect_source.cpp" " void undefined_symbol() {}; ")
++ file(APPEND "${CMAKE_CURRENT_SOURCE_DIR}/incorrect_source.cpp" " void undefined_symbol() {}; ")
+ endif()
+ add_library(l0 SHARED incorrect_source.cpp)
+ add_library(l1 MODULE incorrect_source.cpp)
+@@ -391,7 +391,7 @@ else()
+ endif()
+
+ list(INSERT CMAKE_MODULE_PATH 0
+- "${CMAKE_SOURCE_DIR}/cmake")
++ "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
+
+ if (NOT DEFINED ENV{DEVELOPER_LOCAL_TOOLS})
+ message(STATUS "Could not find DEVELOPER_LOCAL_TOOLS in env (not required)")
+diff --git a/cmake/CheckLinkerFlag.cmake b/cmake/CheckLinkerFlag.cmake
+index 7ecf5f610..89fb9d167 100644
+--- a/cmake/CheckLinkerFlag.cmake
++++ b/cmake/CheckLinkerFlag.cmake
+@@ -6,7 +6,7 @@ macro(CHECK_LINKER_FLAG flag VARIABLE)
+ message(STATUS "Looking for ${flag} linker flag")
+ endif()
+
+- set(_cle_source ${CMAKE_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
++ set(_cle_source ${CMAKE_CURRENT_SOURCE_DIR}/cmake/CheckLinkerFlag.c)
+
+ set(saved_CMAKE_C_FLAGS ${CMAKE_C_FLAGS})
+ set(CMAKE_C_FLAGS "${flag}")
+diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
+index 3cc6b278f..071434486 100644
+--- a/src/wallet/wallet_rpc_server.cpp
++++ b/src/wallet/wallet_rpc_server.cpp
+@@ -1162,7 +1162,7 @@ namespace tools
+ {
+ uint64_t mixin = m_wallet->adjust_mixin(req.ring_size ? req.ring_size - 1 : 0);
+ uint32_t priority = m_wallet->adjust_priority(req.priority);
+- std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, priority, extra, req.account_index, req.subaddr_indices, req.subtract_fee_from_outputs);
++ std::vector<wallet2::pending_tx> ptx_vector = m_wallet->create_transactions_2(dsts, mixin, priority, extra, req.account_index, req.subaddr_indices, {}, req.subtract_fee_from_outputs);
+
+ if (ptx_vector.empty())
+ {
+--
+2.39.5 (Apple Git-154)
+
diff --git a/patches/wownero/0014-fix-iOS-depends-build.patch b/patches/wownero/0014-fix-iOS-depends-build.patch
new file mode 100644
index 0000000..5e97b89
--- /dev/null
+++ b/patches/wownero/0014-fix-iOS-depends-build.patch
@@ -0,0 +1,104 @@
+From f9bf382c57e4a36044e7a0697dc36073487eadd3 Mon Sep 17 00:00:00 2001
+From: Czarek Nakamoto <cyjan@mrcyjanek.net>
+Date: Thu, 21 Nov 2024 06:05:03 -0500
+Subject: [PATCH 14/15] fix iOS depends build
+
+---
+ CMakeLists.txt | 4 ----
+ src/checkpoints/CMakeLists.txt | 6 +++++-
+ src/cryptonote_basic/CMakeLists.txt | 6 +++++-
+ src/cryptonote_basic/miner.cpp | 8 ++++----
+ 4 files changed, 14 insertions(+), 10 deletions(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index 763d240fc..e3a0faacd 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -39,10 +39,6 @@ include(CheckLibraryExists)
+ include(CheckFunctionExists)
+ include(FindPythonInterp)
+
+-if (IOS)
+- INCLUDE(CmakeLists_IOS.txt)
+-endif()
+-
+ cmake_minimum_required(VERSION 3.5)
+ message(STATUS "CMake version ${CMAKE_VERSION}")
+
+diff --git a/src/checkpoints/CMakeLists.txt b/src/checkpoints/CMakeLists.txt
+index 665441f62..841df3256 100644
+--- a/src/checkpoints/CMakeLists.txt
++++ b/src/checkpoints/CMakeLists.txt
+@@ -28,7 +28,11 @@
+
+ if(APPLE)
+ if(DEPENDS)
+- list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
++ if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
++ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework IOKit")
++ else()
++ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
++ endif()
+ else()
+ find_library(IOKIT_LIBRARY IOKit)
+ mark_as_advanced(IOKIT_LIBRARY)
+diff --git a/src/cryptonote_basic/CMakeLists.txt b/src/cryptonote_basic/CMakeLists.txt
+index 414936a05..81c81767f 100644
+--- a/src/cryptonote_basic/CMakeLists.txt
++++ b/src/cryptonote_basic/CMakeLists.txt
+@@ -28,7 +28,11 @@
+
+ if(APPLE)
+ if(DEPENDS)
+- list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
++ if(${CMAKE_SYSTEM_NAME} STREQUAL "iOS")
++ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework IOKit")
++ else()
++ list(APPEND EXTRA_LIBRARIES "-framework Foundation -framework ApplicationServices -framework AppKit -framework IOKit")
++ endif()
+ else()
+ find_library(IOKIT_LIBRARY IOKit)
+ mark_as_advanced(IOKIT_LIBRARY)
+diff --git a/src/cryptonote_basic/miner.cpp b/src/cryptonote_basic/miner.cpp
+index 83bea8b5b..dfb4b5c5a 100644
+--- a/src/cryptonote_basic/miner.cpp
++++ b/src/cryptonote_basic/miner.cpp
+@@ -45,7 +45,7 @@
+ #include "boost/logic/tribool.hpp"
+ #include <boost/filesystem.hpp>
+
+-#ifdef __APPLE__
++#if defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
+ #include <sys/times.h>
+ #include <IOKit/IOKitLib.h>
+ #include <IOKit/ps/IOPSKeys.h>
+@@ -971,7 +971,7 @@ namespace cryptonote
+
+ return true;
+
+- #elif defined(__APPLE__)
++ #elif defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
+
+ mach_msg_type_number_t count;
+ kern_return_t status;
+@@ -1037,7 +1037,7 @@ namespace cryptonote
+ return true;
+ }
+
+- #elif (defined(__linux__) && defined(_SC_CLK_TCK)) || defined(__APPLE__) || defined(__FreeBSD__)
++ #elif (defined(__linux__) && defined(_SC_CLK_TCK)) || (defined(__APPLE__) && !defined(TARGET_OS_IPHONE)) || defined(__FreeBSD__)
+
+ struct tms tms;
+ if ( times(&tms) != (clock_t)-1 )
+@@ -1066,7 +1066,7 @@ namespace cryptonote
+ return boost::logic::tribool(power_status.ACLineStatus != 1);
+ }
+
+- #elif defined(__APPLE__)
++ #elif defined(__APPLE__) && !defined(TARGET_OS_IPHONE)
+
+ #if TARGET_OS_MAC && (!defined(MAC_OS_X_VERSION_MIN_REQUIRED) || MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_7)
+ return boost::logic::tribool(IOPSGetTimeRemainingEstimate() != kIOPSTimeRemainingUnlimited);
+--
+2.39.5 (Apple Git-154)
+
diff --git a/patches/wownero/0015-include-locale-only-when-targeting-WIN32.patch b/patches/wownero/0015-include-locale-only-when-targeting-WIN32.patch
new file mode 100644
index 0000000..512e012
--- /dev/null
+++ b/patches/wownero/0015-include-locale-only-when-targeting-WIN32.patch
@@ -0,0 +1,43 @@
+From a6538084be4fdfbf84e7cbae2bce040aeaf4a4f9 Mon Sep 17 00:00:00 2001
+From: Czarek Nakamoto <cyjan@mrcyjanek.net>
+Date: Mon, 18 Nov 2024 10:57:37 -0500
+Subject: [PATCH 15/15] include locale only when targeting WIN32
+
+---
+ CMakeLists.txt | 5 ++++-
+ src/wallet/api/wallet.cpp | 2 ++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/CMakeLists.txt b/CMakeLists.txt
+index e3a0faacd..b9207ef2a 100644
+--- a/CMakeLists.txt
++++ b/CMakeLists.txt
+@@ -1096,7 +1096,10 @@ if(STATIC)
+ set(Boost_USE_STATIC_LIBS ON)
+ set(Boost_USE_STATIC_RUNTIME ON)
+ endif()
+-find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options locale)
++if(WIN32)
++ set(BOOST_LOCALE locale)
++endif()
++find_package(Boost 1.58 QUIET REQUIRED COMPONENTS system filesystem thread date_time chrono regex serialization program_options ${BOOST_LOCALE})
+ add_definitions(-DBOOST_ASIO_ENABLE_SEQUENTIAL_STRAND_ALLOCATION)
+ add_definitions(-DBOOST_NO_AUTO_PTR)
+ add_definitions(-DBOOST_UUID_DISABLE_ALIGNMENT) # This restores UUID's std::has_unique_object_representations property
+diff --git a/src/wallet/api/wallet.cpp b/src/wallet/api/wallet.cpp
+index e650e6044..6d7553a1d 100644
+--- a/src/wallet/api/wallet.cpp
++++ b/src/wallet/api/wallet.cpp
+@@ -46,7 +46,9 @@
+ #include <sstream>
+ #include <unordered_map>
+
++#ifdef WIN32
+ #include <boost/locale.hpp>
++#endif
+ #include <boost/filesystem.hpp>
+ #include "bc-ur/src/bc-ur.hpp"
+ #if defined(HIDAPI_DUMMY) && !defined(HAVE_HIDAPI)
+--
+2.39.5 (Apple Git-154)
+
diff --git a/patches/wownero/README.md b/patches/wownero/README.md
deleted file mode 100644
index 1aac8bc..0000000
--- a/patches/wownero/README.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# 0000-fix-wallet_api-compilation-target
-
-https://git.wownero.com/wownero/wownero/issues/483
-
-# 0001-polyseed
-
-see monero directory
-
-# 0002-background-sync
-
-see monero directory
-
-# 0003-airgap
-
-see monero directory
-
-# 0004-coin-control
-
-Small fix to make it compatible with monero's implementation - to have the same standard API.
-
-# 0005-fix-build
-
-see monero directory
-
-# 0006-macos-build-fix
-
-see monero directory
-
-# 0007-FIX-wallet-listener-crashing
-
-https://git.wownero.com/wownero/wownero/issues/484
-
-# 0008-fix-missing-___clear_cache-when-targetting-iOS
-
-https://git.wownero.com/wownero/RandomWOW/pulls/2 \ No newline at end of file