diff options
| author | Mateusz Franik <47059999+Im-Beast@users.noreply.github.com> | 2024-12-19 13:19:33 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-12-19 13:19:33 +0100 |
| commit | 10c0df93ff92c2001ed5aa2b22e5db85ab91242e (patch) | |
| tree | c08ce2f21126bd956b118aa4908d9a69d79b3e7f /patches | |
| parent | 7d8db85942194fc7576d58beb7a4dc65e415a56b (diff) | |
| parent | 2a38bf29618a8ce163f9d6f83b7ae86924752e32 (diff) | |
Merge branch 'develop' into tests-other-platforms
Diffstat (limited to 'patches')
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 ¬e) { @@ -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 ¬e) +@@ -1852,6 +2012,8 @@ bool WalletImpl::setUserNote(const std::string &txid, const std::string ¬e) 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 ¤t_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>> ®istry); + +- #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 ¬e) { @@ -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 ¬e) +@@ -1852,6 +2012,8 @@ bool WalletImpl::setUserNote(const std::string &txid, const std::string ¬e) 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 ¤t_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 |
