diff options
Diffstat (limited to 'src/simplewallet')
-rw-r--r-- | src/simplewallet/CMakeLists.txt | 5 | ||||
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 332 | ||||
-rw-r--r-- | src/simplewallet/simplewallet.h | 8 |
3 files changed, 182 insertions, 163 deletions
diff --git a/src/simplewallet/CMakeLists.txt b/src/simplewallet/CMakeLists.txt index a0820c8eb..b659d9f48 100644 --- a/src/simplewallet/CMakeLists.txt +++ b/src/simplewallet/CMakeLists.txt @@ -1,4 +1,4 @@ -# Copyright (c) 2014-2020, The Monero Project +# Copyright (c) 2014-2022, The Monero Project # # All rights reserved. # @@ -31,8 +31,7 @@ set(simplewallet_sources set(simplewallet_headers) -set(simplewallet_private_headers - simplewallet.h) +monero_find_all_headers(simplewallet_private_headers "${CMAKE_CURRENT_SOURCE_DIR}") monero_private_headers(simplewallet ${simplewallet_private_headers}) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index dc031b36c..a8f4e5a07 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -99,10 +99,6 @@ typedef cryptonote::simple_wallet sw; #define EXTENDED_LOGS_FILE "wallet_details.log" -#define DEFAULT_MIX 10 - -#define MIN_RING_SIZE 11 // Used to inform user about min ring size -- does not track actual protocol - #define OLD_AGE_WARN_THRESHOLD (30 * 86400 / DIFFICULTY_TARGET_V2) // 30 days #define LOCK_IDLE_SCOPE() \ @@ -146,6 +142,19 @@ typedef cryptonote::simple_wallet sw; #define MIN_PAYMENT_RATE 0.01f // per hash #define MAX_MNEW_ADDRESSES 1000 +#define CHECK_MULTISIG_ENABLED() \ + do \ + { \ + if (!m_wallet->is_multisig_enabled()) \ + { \ + fail_msg_writer() << tr("Multisig is disabled."); \ + fail_msg_writer() << tr("Multisig is an experimental feature and may have bugs. Things that could go wrong include: funds sent to a multisig wallet can't be spent at all, can only be spent with the participation of a malicious group member, or can be stolen by a malicious group member."); \ + fail_msg_writer() << tr("You can enable it with:"); \ + fail_msg_writer() << tr(" set enable-multisig-experimental 1"); \ + return false; \ + } \ + } while(0) + enum TransferType { Transfer, TransferLocked, @@ -235,7 +244,6 @@ namespace const char* USAGE_IMPORT_OUTPUTS("import_outputs <filename>"); const char* USAGE_SHOW_TRANSFER("show_transfer <txid>"); const char* USAGE_MAKE_MULTISIG("make_multisig <threshold> <string1> [<string>...]"); - const char* USAGE_FINALIZE_MULTISIG("finalize_multisig <string> [<string>...]"); const char* USAGE_EXCHANGE_MULTISIG_KEYS("exchange_multisig_keys <string> [<string>...]"); const char* USAGE_EXPORT_MULTISIG_INFO("export_multisig_info <filename>"); const char* USAGE_IMPORT_MULTISIG_INFO("import_multisig_info <filename> [<filename>...]"); @@ -991,12 +999,14 @@ bool simple_wallet::print_fee_info(const std::vector<std::string> &args/* = std: bool simple_wallet::prepare_multisig(const std::vector<std::string> &args) { + CHECK_MULTISIG_ENABLED(); prepare_multisig_main(args, false); return true; } bool simple_wallet::prepare_multisig_main(const std::vector<std::string> &args, bool called_by_mms) { + CHECK_MULTISIG_ENABLED(); if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); @@ -1021,7 +1031,7 @@ bool simple_wallet::prepare_multisig_main(const std::vector<std::string> &args, SCOPED_WALLET_UNLOCK_ON_BAD_PASSWORD(return false;); - std::string multisig_info = m_wallet->get_multisig_info(); + std::string multisig_info = m_wallet->get_multisig_first_kex_msg(); success_msg_writer() << multisig_info; success_msg_writer() << tr("Send this multisig info to all other participants, then use make_multisig <threshold> <info1> [<info2>...] with others' multisig info"); success_msg_writer() << tr("This includes the PRIVATE view key, so needs to be disclosed only to that multisig wallet's participants "); @@ -1036,12 +1046,14 @@ bool simple_wallet::prepare_multisig_main(const std::vector<std::string> &args, bool simple_wallet::make_multisig(const std::vector<std::string> &args) { + CHECK_MULTISIG_ENABLED(); make_multisig_main(args, false); return true; } bool simple_wallet::make_multisig_main(const std::vector<std::string> &args, bool called_by_mms) { + CHECK_MULTISIG_ENABLED(); if (m_wallet->key_on_device()) { fail_msg_writer() << tr("command not supported by HW wallet"); @@ -1092,7 +1104,9 @@ bool simple_wallet::make_multisig_main(const std::vector<std::string> &args, boo auto local_args = args; local_args.erase(local_args.begin()); std::string multisig_extra_info = m_wallet->make_multisig(orig_pwd_container->password(), local_args, threshold); - if (!multisig_extra_info.empty()) + bool ready; + m_wallet->multisig(&ready); + if (!ready) { success_msg_writer() << tr("Another step is needed"); success_msg_writer() << multisig_extra_info; @@ -1122,65 +1136,15 @@ bool simple_wallet::make_multisig_main(const std::vector<std::string> &args, boo return true; } -bool simple_wallet::finalize_multisig(const std::vector<std::string> &args) -{ - bool ready; - if (m_wallet->key_on_device()) - { - fail_msg_writer() << tr("command not supported by HW wallet"); - return true; - } - - const auto pwd_container = get_and_verify_password(); - if(pwd_container == boost::none) - { - fail_msg_writer() << tr("Your original password was incorrect."); - return true; - } - - if (!m_wallet->multisig(&ready)) - { - fail_msg_writer() << tr("This wallet is not multisig"); - return true; - } - if (ready) - { - fail_msg_writer() << tr("This wallet is already finalized"); - return true; - } - - LOCK_IDLE_SCOPE(); - - if (args.size() < 2) - { - PRINT_USAGE(USAGE_FINALIZE_MULTISIG); - return true; - } - - try - { - if (!m_wallet->finalize_multisig(pwd_container->password(), args)) - { - fail_msg_writer() << tr("Failed to finalize multisig"); - return true; - } - } - catch (const std::exception &e) - { - fail_msg_writer() << tr("Failed to finalize multisig: ") << e.what(); - return true; - } - - return true; -} - bool simple_wallet::exchange_multisig_keys(const std::vector<std::string> &args) { + CHECK_MULTISIG_ENABLED(); exchange_multisig_keys_main(args, false); return true; } bool simple_wallet::exchange_multisig_keys_main(const std::vector<std::string> &args, bool called_by_mms) { + CHECK_MULTISIG_ENABLED(); bool ready; if (m_wallet->key_on_device()) { @@ -1205,7 +1169,7 @@ bool simple_wallet::exchange_multisig_keys_main(const std::vector<std::string> & return false; } - if (args.size() < 2) + if (args.size() < 1) { PRINT_USAGE(USAGE_EXCHANGE_MULTISIG_KEYS); return false; @@ -1214,7 +1178,9 @@ bool simple_wallet::exchange_multisig_keys_main(const std::vector<std::string> & try { std::string multisig_extra_info = m_wallet->exchange_multisig_keys(orig_pwd_container->password(), args); - if (!multisig_extra_info.empty()) + bool ready; + m_wallet->multisig(&ready); + if (!ready) { message_writer() << tr("Another step is needed"); message_writer() << multisig_extra_info; @@ -1242,12 +1208,14 @@ bool simple_wallet::exchange_multisig_keys_main(const std::vector<std::string> & bool simple_wallet::export_multisig(const std::vector<std::string> &args) { + CHECK_MULTISIG_ENABLED(); export_multisig_main(args, false); return true; } bool simple_wallet::export_multisig_main(const std::vector<std::string> &args, bool called_by_mms) { + CHECK_MULTISIG_ENABLED(); bool ready; if (m_wallet->key_on_device()) { @@ -1307,12 +1275,14 @@ bool simple_wallet::export_multisig_main(const std::vector<std::string> &args, b bool simple_wallet::import_multisig(const std::vector<std::string> &args) { + CHECK_MULTISIG_ENABLED(); import_multisig_main(args, false); return true; } bool simple_wallet::import_multisig_main(const std::vector<std::string> &args, bool called_by_mms) { + CHECK_MULTISIG_ENABLED(); bool ready; uint32_t threshold, total; if (m_wallet->key_on_device()) @@ -1402,12 +1372,14 @@ bool simple_wallet::accept_loaded_tx(const tools::wallet2::multisig_tx_set &txs) bool simple_wallet::sign_multisig(const std::vector<std::string> &args) { + CHECK_MULTISIG_ENABLED(); sign_multisig_main(args, false); return true; } bool simple_wallet::sign_multisig_main(const std::vector<std::string> &args, bool called_by_mms) { + CHECK_MULTISIG_ENABLED(); bool ready; if (m_wallet->key_on_device()) { @@ -1517,12 +1489,14 @@ bool simple_wallet::sign_multisig_main(const std::vector<std::string> &args, boo bool simple_wallet::submit_multisig(const std::vector<std::string> &args) { + CHECK_MULTISIG_ENABLED(); submit_multisig_main(args, false); return true; } bool simple_wallet::submit_multisig_main(const std::vector<std::string> &args, bool called_by_mms) { + CHECK_MULTISIG_ENABLED(); bool ready; uint32_t threshold; if (m_wallet->key_on_device()) @@ -1604,6 +1578,7 @@ bool simple_wallet::submit_multisig_main(const std::vector<std::string> &args, b bool simple_wallet::export_raw_multisig(const std::vector<std::string> &args) { + CHECK_MULTISIG_ENABLED(); bool ready; uint32_t threshold; if (m_wallet->key_on_device()) @@ -2525,59 +2500,6 @@ bool simple_wallet::set_store_tx_info(const std::vector<std::string> &args/* = s return true; } -bool simple_wallet::set_default_ring_size(const std::vector<std::string> &args/* = std::vector<std::string>()*/) -{ - if (m_wallet->watch_only()) - { - fail_msg_writer() << tr("wallet is watch-only and cannot transfer"); - return true; - } - try - { - if (strchr(args[1].c_str(), '-')) - { - fail_msg_writer() << tr("ring size must be an integer >= ") << MIN_RING_SIZE; - return true; - } - uint32_t ring_size = boost::lexical_cast<uint32_t>(args[1]); - if (ring_size < MIN_RING_SIZE && ring_size != 0) - { - fail_msg_writer() << tr("ring size must be an integer >= ") << MIN_RING_SIZE; - return true; - } - - if (ring_size != 0 && ring_size != DEFAULT_MIX+1) - { - if (m_wallet->use_fork_rules(8, 0)) - { - message_writer() << tr("WARNING: from v8, ring size will be fixed and this setting will be ignored."); - } - else - { - message_writer() << tr("WARNING: this is a non default ring size, which may harm your privacy. Default is recommended."); - } - } - - const auto pwd_container = get_and_verify_password(); - if (pwd_container) - { - m_wallet->default_mixin(ring_size > 0 ? ring_size - 1 : 0); - m_wallet->rewrite(m_wallet_file, pwd_container->password()); - } - return true; - } - catch(const boost::bad_lexical_cast &) - { - fail_msg_writer() << tr("ring size must be an integer >= ") << MIN_RING_SIZE; - return true; - } - catch(...) - { - fail_msg_writer() << tr("could not change default ring size"); - return true; - } -} - bool simple_wallet::set_default_priority(const std::vector<std::string> &args/* = std::vector<std::string>()*/) { uint32_t priority = 0; @@ -3041,6 +2963,19 @@ bool simple_wallet::set_track_uses(const std::vector<std::string> &args/* = std: 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(); + if (pwd_container) + { + parse_bool_and_use(args[1], [&](bool r) { + m_wallet->show_wallet_name_when_locked(r); + m_wallet->rewrite(m_wallet_file, pwd_container->password()); + }); + } + return true; +} + bool simple_wallet::set_inactivity_lock_timeout(const std::vector<std::string> &args/* = std::vector<std::string>()*/) { #ifdef _WIN32 @@ -3167,6 +3102,25 @@ bool simple_wallet::set_load_deprecated_formats(const std::vector<std::string> & return true; } +bool simple_wallet::set_enable_multisig(const std::vector<std::string> &args/* = std::vector<std::string>()*/) +{ + if (args.size() < 2) + { + fail_msg_writer() << tr("Value not specified"); + return true; + } + + const auto pwd_container = get_and_verify_password(); + if (pwd_container) + { + parse_bool_and_use(args[1], [&](bool r) { + m_wallet->enable_multisig(r); + m_wallet->rewrite(m_wallet_file, pwd_container->password()); + }); + } + return true; +} + bool simple_wallet::help(const std::vector<std::string> &args/* = std::vector<std::string>()*/) { if(args.empty()) @@ -3426,8 +3380,6 @@ simple_wallet::simple_wallet() " Whether to print detailed information about ring members during confirmation.\n " "store-tx-info <1|0>\n " " Whether to store outgoing tx info (destination address, payment ID, tx secret key) for future reference.\n " - "default-ring-size <n>\n " - " Set the default ring size (obsolete).\n " "auto-refresh <1|0>\n " " Whether to automatically synchronize new blocks from the daemon.\n " "refresh-type <full|optimize-coinbase|no-coinbase|default>\n " @@ -3484,6 +3436,10 @@ simple_wallet::simple_wallet() " Whether to automatically start mining for RPC payment if the daemon requires it.\n" "credits-target <unsigned int>\n" " The RPC payment credits balance to target (0 for default).\n " + "show-wallet-name-when-locked <1|0>\n " + " Set this if you would like to display the wallet name when locked.\n " + "enable-multisig-experimental <1|0>\n " + " Set this to allow multisig commands. Multisig may currently be exploitable if parties do not trust each other.\n " "inactivity-lock-timeout <unsigned int>\n " " How many seconds to wait before locking the wallet (0 to disable).")); m_cmd_binder.set_handler("encrypted_seed", @@ -3544,7 +3500,7 @@ simple_wallet::simple_wallet() "** Set of address indices used as inputs in this transfer.")); m_cmd_binder.set_handler("export_transfers", boost::bind(&simple_wallet::on_command, this, &simple_wallet::export_transfers, _1), - tr("export_transfers [in|out|all|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<filepath>]"), + tr("export_transfers [in|out|all|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<filepath>] [option=<with_keys>]"), tr("Export to CSV the incoming/outgoing transfers within an optional height range.")); m_cmd_binder.set_handler("unspent_outputs", boost::bind(&simple_wallet::on_command, this, &simple_wallet::unspent_outputs, _1), @@ -3627,10 +3583,6 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("make_multisig", boost::bind(&simple_wallet::on_command, this, &simple_wallet::make_multisig, _1), tr(USAGE_MAKE_MULTISIG), tr("Turn this wallet into a multisig wallet")); - m_cmd_binder.set_handler("finalize_multisig", - boost::bind(&simple_wallet::on_command, this, &simple_wallet::finalize_multisig, _1), - tr(USAGE_FINALIZE_MULTISIG), - tr("Turn this wallet into a multisig wallet, extra step for N-1/N wallets")); m_cmd_binder.set_handler("exchange_multisig_keys", boost::bind(&simple_wallet::on_command, this, &simple_wallet::exchange_multisig_keys, _1), tr(USAGE_EXCHANGE_MULTISIG_KEYS), @@ -3893,6 +3845,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args) 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"); + success_msg_writer() << "show-wallet-name-when-locked = " << m_wallet->show_wallet_name_when_locked(); success_msg_writer() << "inactivity-lock-timeout = " << m_wallet->inactivity_lock_timeout() #ifdef _WIN32 << " (disabled on Windows)" @@ -3902,6 +3855,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args) success_msg_writer() << "auto-mine-for-rpc-payment-threshold = " << m_wallet->auto_mine_for_rpc_payment_threshold(); success_msg_writer() << "credits-target = " << m_wallet->credits_target(); success_msg_writer() << "load-deprecated-formats = " << m_wallet->load_deprecated_formats(); + success_msg_writer() << "enable-multisig-experimental = " << m_wallet->is_multisig_enabled(); return true; } else @@ -3937,7 +3891,6 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args) CHECK_SIMPLE_VARIABLE("always-confirm-transfers", set_always_confirm_transfers, tr("0 or 1")); CHECK_SIMPLE_VARIABLE("print-ring-members", set_print_ring_members, tr("0 or 1")); CHECK_SIMPLE_VARIABLE("store-tx-info", set_store_tx_info, tr("0 or 1")); - CHECK_SIMPLE_VARIABLE("default-ring-size", set_default_ring_size, tr("integer >= ") << MIN_RING_SIZE); CHECK_SIMPLE_VARIABLE("auto-refresh", set_auto_refresh, tr("0 or 1")); CHECK_SIMPLE_VARIABLE("refresh-type", set_refresh_type, tr("full (slowest, no assumptions); optimize-coinbase (fast, assumes the whole coinbase is paid to a single address); no-coinbase (fastest, assumes we receive no coinbase transaction), default (same as optimize-coinbase)")); CHECK_SIMPLE_VARIABLE("priority", set_default_priority, tr("0, 1, 2, 3, or 4, or one of ") << join_priority_strings(", ")); @@ -3960,6 +3913,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("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")); CHECK_SIMPLE_VARIABLE("device-name", set_device_name, tr("<device_name[:device_spec]>")); @@ -3968,6 +3922,7 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args) CHECK_SIMPLE_VARIABLE("persistent-rpc-client-id", set_persistent_rpc_client_id, tr("0 or 1")); CHECK_SIMPLE_VARIABLE("auto-mine-for-rpc-payment-threshold", set_auto_mine_for_rpc_payment_threshold, tr("floating point >= 0")); CHECK_SIMPLE_VARIABLE("credits-target", set_credits_target, tr("unsigned integer")); + CHECK_SIMPLE_VARIABLE("enable-multisig-experimental", set_enable_multisig, tr("0 or 1")); } fail_msg_writer() << tr("set: unrecognized argument(s)"); return true; @@ -5718,14 +5673,18 @@ void simple_wallet::on_new_block(uint64_t height, const cryptonote::block& block m_refresh_progress_reporter.update(height, false); } //---------------------------------------------------------------------------------------------------- -void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time) +void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, uint64_t burnt, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time) { if (m_locked) return; + std::stringstream burn; + if (burnt != 0) { + burn << " (" << print_money(amount) << " yet " << print_money(burnt) << " was burnt)"; + } message_writer(console_color_green, false) << "\r" << tr("Height ") << height << ", " << tr("txid ") << txid << ", " << - print_money(amount) << ", " << + print_money(amount - burnt) << burn.str() << ", " << tr("idx ") << subaddr_index; const uint64_t warn_height = m_wallet->nettype() == TESTNET ? 1000000 : m_wallet->nettype() == STAGENET ? 50000 : 1650000; @@ -6061,6 +6020,7 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args auto local_args = args; LOCK_IDLE_SCOPE(); + std::set<uint32_t> subaddr_indices; bool filter = false; bool available = false; bool verbose = false; @@ -6086,6 +6046,11 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args verbose = true; else if (local_args[0] == "uses") uses = true; + else if (local_args[0].substr(0, 6) == "index=") + { + if (!parse_subaddress_indices(local_args[0], subaddr_indices)) + return true; + } else { fail_msg_writer() << tr("Invalid keyword: ") << local_args.front(); @@ -6098,14 +6063,6 @@ bool simple_wallet::show_incoming_transfers(const std::vector<std::string>& args PAUSE_READLINE(); - std::set<uint32_t> subaddr_indices; - if (local_args.size() > 0 && local_args[0].substr(0, 6) == "index=") - { - if (!parse_subaddress_indices(local_args[0], subaddr_indices)) - return true; - local_args.erase(local_args.begin()); - } - if (local_args.size() > 0) { PRINT_USAGE(USAGE_INCOMING_TRANSFERS); @@ -6522,6 +6479,16 @@ void simple_wallet::check_for_inactivity_lock(bool user) { const char *inactivity_msg = user ? "" : tr("Locked due to inactivity."); tools::msg_writer() << inactivity_msg << (inactivity_msg[0] ? " " : "") << tr("The wallet password is required to unlock the console."); + + const bool show_wallet_name = m_wallet->show_wallet_name_when_locked(); + if (show_wallet_name) + { + tools::msg_writer() << tr("Filename: ") << m_wallet->get_wallet_file(); + tools::msg_writer() << tr("Network type: ") << ( + m_wallet->nettype() == cryptonote::TESTNET ? tr("Testnet") : + m_wallet->nettype() == cryptonote::STAGENET ? tr("Stagenet") : tr("Mainnet") + ); + } try { if (get_and_verify_password()) @@ -6571,7 +6538,8 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri priority = m_wallet->adjust_priority(priority); - size_t fake_outs_count = DEFAULT_MIX; + const size_t min_ring_size = m_wallet->get_min_ring_size(); + size_t fake_outs_count = min_ring_size - 1; if(local_args.size() > 0) { size_t ring_size; if(!epee::string_tools::get_xtype_from_string(ring_size, local_args[0])) @@ -6647,7 +6615,6 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri vector<cryptonote::address_parse_info> dsts_info; vector<cryptonote::tx_destination_entry> dsts; - size_t num_subaddresses = 0; for (size_t i = 0; i < local_args.size(); ) { dsts_info.emplace_back(); @@ -6706,7 +6673,6 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri de.addr = info.address; de.is_subaddress = info.is_subaddress; de.is_integrated = info.has_payment_id; - num_subaddresses += info.is_subaddress; if (info.has_payment_id || !payment_id_uri.empty()) { @@ -6894,7 +6860,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri if (vin.type() == typeid(txin_to_key)) { const txin_to_key& in_to_key = boost::get<txin_to_key>(vin); - if (in_to_key.key_offsets.size() != DEFAULT_MIX + 1) + if (in_to_key.key_offsets.size() != min_ring_size) default_ring_size = false; } } @@ -6998,18 +6964,33 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri //---------------------------------------------------------------------------------------------------- bool simple_wallet::transfer(const std::vector<std::string> &args_) { + if (args_.size() < 1) + { + PRINT_USAGE(USAGE_TRANSFER); + return true; + } transfer_main(Transfer, args_, false); return true; } //---------------------------------------------------------------------------------------------------- bool simple_wallet::locked_transfer(const std::vector<std::string> &args_) { + if (args_.size() < 1) + { + PRINT_USAGE(USAGE_LOCKED_TRANSFER); + return true; + } transfer_main(TransferLocked, args_, false); return true; } //---------------------------------------------------------------------------------------------------- bool simple_wallet::locked_sweep_all(const std::vector<std::string> &args_) { + if (args_.size() < 1) + { + PRINT_USAGE(USAGE_LOCKED_SWEEP_ALL); + return true; + } sweep_main(m_current_subaddress_account, 0, true, args_); return true; } @@ -7067,6 +7048,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_) // actually commit the transactions if (m_wallet->multisig()) { + CHECK_MULTISIG_ENABLED(); bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx"); if (!r) { @@ -7172,7 +7154,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co priority = m_wallet->adjust_priority(priority); - size_t fake_outs_count = DEFAULT_MIX; + size_t fake_outs_count = m_wallet->get_min_ring_size() - 1; if(local_args.size() > 0) { size_t ring_size; if(!epee::string_tools::get_xtype_from_string(ring_size, local_args[0])) @@ -7371,6 +7353,7 @@ bool simple_wallet::sweep_main(uint32_t account, uint64_t below, bool locked, co // actually commit the transactions if (m_wallet->multisig()) { + CHECK_MULTISIG_ENABLED(); bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx"); if (!r) { @@ -7449,7 +7432,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_) priority = m_wallet->adjust_priority(priority); - size_t fake_outs_count = DEFAULT_MIX; + size_t fake_outs_count = m_wallet->get_min_ring_size() - 1; if(local_args.size() > 0) { size_t ring_size; if(!epee::string_tools::get_xtype_from_string(ring_size, local_args[0])) @@ -7605,6 +7588,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_) // actually commit the transactions if (m_wallet->multisig()) { + CHECK_MULTISIG_ENABLED(); bool r = m_wallet->save_multisig_tx(ptx_vector, "multisig_monero_tx"); if (!r) { @@ -7705,6 +7689,7 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_) if (args_.size() < 1) { fail_msg_writer() << tr("missing threshold amount"); + PRINT_USAGE(USAGE_SWEEP_BELOW); return true; } if (!cryptonote::parse_amount(below, args_[0])) @@ -8053,6 +8038,15 @@ bool simple_wallet::submit_transfer(const std::vector<std::string> &args_) return true; } //---------------------------------------------------------------------------------------------------- +std::string get_tx_key_stream(crypto::secret_key tx_key, std::vector<crypto::secret_key> additional_tx_keys) +{ + ostringstream oss; + oss << epee::string_tools::pod_to_hex(tx_key); + for (size_t i = 0; i < additional_tx_keys.size(); ++i) + oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]); + return oss.str(); +} + bool simple_wallet::get_tx_key(const std::vector<std::string> &args_) { std::vector<std::string> local_args = args_; @@ -8082,11 +8076,8 @@ bool simple_wallet::get_tx_key(const std::vector<std::string> &args_) bool found_tx_key = m_wallet->get_tx_key(txid, tx_key, additional_tx_keys); if (found_tx_key) { - ostringstream oss; - oss << epee::string_tools::pod_to_hex(tx_key); - for (size_t i = 0; i < additional_tx_keys.size(); ++i) - oss << epee::string_tools::pod_to_hex(additional_tx_keys[i]); - success_msg_writer() << tr("Tx key: ") << oss.str(); + std::string stream = get_tx_key_stream(tx_key, additional_tx_keys); + success_msg_writer() << tr("Tx key: ") << stream; return true; } else @@ -8897,13 +8888,11 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_) { std::vector<std::string> local_args = args_; - if(local_args.size() > 5) { - fail_msg_writer() << tr("usage: export_transfers [in|out|all|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<path>]"); + if(local_args.size() > 6) { + fail_msg_writer() << tr("usage: export_transfers [in|out|all|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]] [output=<path>] [option=<with_keys>]"); return true; } - LOCK_IDLE_SCOPE(); - std::vector<transfer_view> all_transfers; // might consumes arguments in local_args @@ -8917,17 +8906,36 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_) filename = local_args[0].substr(7, -1); local_args.erase(local_args.begin()); } + // check for export with tx keys + bool export_keys = false; + if (local_args.size() > 0 && local_args[0].substr(0, 7) == "option=") + { + export_keys = local_args[0].substr(7, -1) == "with_keys"; + local_args.erase(local_args.begin()); + } + if (export_keys) + { + if (m_wallet->key_on_device() && m_wallet->get_account().get_device().get_type() != hw::device::TREZOR) + { + fail_msg_writer() << tr("command not supported by HW wallet"); + return true; + } + SCOPED_WALLET_UNLOCK(); + } else + { + LOCK_IDLE_SCOPE(); + } std::ofstream file(filename); // header file << - boost::format("%8.8s,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,%s,%s") % - tr("block") % tr("direction") % tr("unlocked") % tr("timestamp") % tr("amount") % tr("running balance") % tr("hash") % tr("payment ID") % tr("fee") % tr("destination") % tr("amount") % tr("index") % tr("note") + boost::format("%8.8s,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,%s,%s,%s") % + tr("block") % tr("direction") % tr("unlocked") % tr("timestamp") % tr("amount") % tr("running balance") % tr("hash") % tr("payment ID") % tr("fee") % tr("destination") % tr("amount") % tr("index") % tr("note") % tr("tx key") << std::endl; uint64_t running_balance = 0; - auto formatter = boost::format("%8.8llu,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,\"%s\",%s"); + auto formatter = boost::format("%8.8llu,%9.9s,%8.8s,%25.25s,%20.20s,%20.20s,%64.64s,%16.16s,%14.14s,%106.106s,%20.20s,\"%s\",%s,%s"); for (const auto& transfer : all_transfers) { @@ -8940,6 +8948,15 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_) running_balance -= transfer.amount + transfer.fee; } + crypto::secret_key tx_key; + std::vector<crypto::secret_key> additional_tx_keys; + bool found_tx_key = m_wallet->get_tx_key(transfer.hash, tx_key, additional_tx_keys); + std::string key_string; + if (export_keys && found_tx_key) + { + key_string = get_tx_key_stream(tx_key, additional_tx_keys); + } + file << formatter % transfer.block % transfer.direction @@ -8954,6 +8971,7 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_) % (transfer.outputs.size() ? print_money(transfer.outputs[0].second) : "") % boost::algorithm::join(transfer.index | boost::adaptors::transformed([](uint32_t i) { return std::to_string(i); }), ", ") % transfer.note + % key_string << std::endl; for (size_t i = 1; i < transfer.outputs.size(); ++i) @@ -8972,6 +8990,7 @@ bool simple_wallet::export_transfers(const std::vector<std::string>& args_) % print_money(transfer.outputs[i].second) % "" % "" + % "" << std::endl; } } @@ -9593,8 +9612,8 @@ void simple_wallet::print_accounts(const std::string& tag) total_balance += m_wallet->balance(account_index, false); total_unlocked_balance += m_wallet->unlocked_balance(account_index, false); } - success_msg_writer() << tr("----------------------------------------------------------------------------------"); - success_msg_writer() << boost::format(tr("%15s %21s %21s")) % "Total" % print_money(total_balance) % print_money(total_unlocked_balance); + success_msg_writer() << tr("------------------------------------------------------------------------------------"); + success_msg_writer() << boost::format(tr("%15s %21s %21s")) % "Total" % print_money(total_balance) % print_money(total_unlocked_balance); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::print_address(const std::vector<std::string> &args/* = std::vector<std::string>()*/) @@ -9818,7 +9837,7 @@ bool simple_wallet::print_integrated_address(const std::vector<std::string> &arg { if (info.has_payment_id) { - success_msg_writer() << boost::format(tr("Integrated address: %s, payment ID: %s")) % + success_msg_writer() << boost::format(tr("Standard address: %s, payment ID: %s")) % get_account_address_as_str(m_wallet->nettype(), false, info.address) % epee::string_tools::pod_to_hex(info.payment_id); device_show_integrated(info.payment_id); } @@ -10973,8 +10992,8 @@ void simple_wallet::mms_init(const std::vector<std::string> &args) std::vector<std::string> numbers; boost::split(numbers, mn, boost::is_any_of("/")); bool mn_ok = (numbers.size() == 2) - && get_number_from_arg(numbers[1], num_authorized_signers, 2, 100) - && get_number_from_arg(numbers[0], num_required_signers, 2, num_authorized_signers); + && get_number_from_arg(numbers[1], num_authorized_signers, 2, config::MULTISIG_MAX_SIGNERS) + && get_number_from_arg(numbers[0], num_required_signers, 1, num_authorized_signers); if (!mn_ok) { fail_msg_writer() << tr("Error in the number of required signers and/or authorized signers"); @@ -11602,6 +11621,7 @@ void simple_wallet::mms_auto_config(const std::vector<std::string> &args) bool simple_wallet::mms(const std::vector<std::string> &args) { + CHECK_MULTISIG_ENABLED(); try { m_wallet->get_multisig_wallet_state(); diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index 8780bee1d..6a9fa149d 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -1,4 +1,4 @@ -// Copyright (c) 2014-2020, The Monero Project +// Copyright (c) 2014-2022, The Monero Project // // All rights reserved. // @@ -125,7 +125,6 @@ namespace cryptonote bool set_always_confirm_transfers(const std::vector<std::string> &args = std::vector<std::string>()); bool set_print_ring_members(const std::vector<std::string> &args = std::vector<std::string>()); bool set_store_tx_info(const std::vector<std::string> &args = std::vector<std::string>()); - bool set_default_ring_size(const std::vector<std::string> &args = std::vector<std::string>()); bool set_auto_refresh(const std::vector<std::string> &args = std::vector<std::string>()); bool set_refresh_type(const std::vector<std::string> &args = std::vector<std::string>()); bool set_confirm_missing_payment_id(const std::vector<std::string> &args = std::vector<std::string>()); @@ -148,11 +147,13 @@ namespace cryptonote bool set_ignore_outputs_above(const std::vector<std::string> &args = std::vector<std::string>()); bool set_ignore_outputs_below(const std::vector<std::string> &args = std::vector<std::string>()); bool set_track_uses(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_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>()); bool set_device_name(const std::vector<std::string> &args = std::vector<std::string>()); bool set_export_format(const std::vector<std::string> &args = std::vector<std::string>()); bool set_load_deprecated_formats(const std::vector<std::string> &args = std::vector<std::string>()); + bool set_enable_multisig(const std::vector<std::string> &args = std::vector<std::string>()); bool set_persistent_rpc_client_id(const std::vector<std::string> &args = std::vector<std::string>()); bool set_auto_mine_for_rpc_payment_threshold(const std::vector<std::string> &args = std::vector<std::string>()); bool set_credits_target(const std::vector<std::string> &args = std::vector<std::string>()); @@ -233,7 +234,6 @@ namespace cryptonote bool prepare_multisig_main(const std::vector<std::string>& args, bool called_by_mms); bool make_multisig(const std::vector<std::string>& args); bool make_multisig_main(const std::vector<std::string>& args, bool called_by_mms); - bool finalize_multisig(const std::vector<std::string> &args); bool exchange_multisig_keys(const std::vector<std::string> &args); bool exchange_multisig_keys_main(const std::vector<std::string> &args, bool called_by_mms); bool export_multisig(const std::vector<std::string>& args); @@ -346,7 +346,7 @@ namespace cryptonote //----------------- i_wallet2_callback --------------------- virtual void on_new_block(uint64_t height, const cryptonote::block& block); - virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time); + virtual void on_money_received(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx, uint64_t amount, uint64_t burnt, const cryptonote::subaddress_index& subaddr_index, bool is_change, uint64_t unlock_time); 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); virtual void on_money_spent(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& in_tx, uint64_t amount, const cryptonote::transaction& spend_tx, const cryptonote::subaddress_index& subaddr_index); virtual void on_skip_transaction(uint64_t height, const crypto::hash &txid, const cryptonote::transaction& tx); |