diff options
Diffstat (limited to 'src/simplewallet/simplewallet.cpp')
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 238 |
1 files changed, 54 insertions, 184 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index f5a469af4..e925e81b5 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -101,6 +101,7 @@ enum TransferType { namespace { + const auto allowed_priority_strings = {"default", "unimportant", "normal", "elevated", "priority"}; const auto arg_wallet_file = wallet_args::arg_wallet_file(); const command_line::arg_descriptor<std::string> arg_generate_new_wallet = {"generate-new-wallet", sw::tr("Generate new wallet and save it to <arg>"), ""}; const command_line::arg_descriptor<std::string> arg_generate_from_view_key = {"generate-from-view-key", sw::tr("Generate incoming-only wallet from view key"), ""}; @@ -559,12 +560,6 @@ bool simple_wallet::set_refresh_type(const std::vector<std::string> &args/* = st bool simple_wallet::set_confirm_missing_payment_id(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; - } - const auto pwd_container = get_and_verify_password(); if (pwd_container) { @@ -685,7 +680,7 @@ simple_wallet::simple_wallet() m_cmd_binder.set_handler("payments", boost::bind(&simple_wallet::show_payments, this, _1), tr("payments <PID_1> [<PID_2> ... <PID_N>] - Show payments for given payment ID[s]")); m_cmd_binder.set_handler("bc_height", boost::bind(&simple_wallet::show_blockchain_height, this, _1), tr("Show blockchain height")); m_cmd_binder.set_handler("transfer_original", boost::bind(&simple_wallet::transfer, this, _1), tr("Same as transfer, but using an older transaction building algorithm")); - m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer_new, this, _1), tr("transfer [<mixin_count>] <address> <amount> [<payment_id>] - Transfer <amount> to <address>. <mixin_count> is the number of extra inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included)")); + m_cmd_binder.set_handler("transfer", boost::bind(&simple_wallet::transfer_new, this, _1), tr("transfer [<priority>] [<mixin_count>] <address> <amount> [<payment_id>] - Transfer <amount> to <address>. <priority> is the priority of the transaction. The higher the priority, the higher the fee of the transaction. Valid values in priority order (from lowest to highest) are: unimportant, normal, elevated, priority. If omitted, the default value (see the command \"set priority\") is used. <mixin_count> is the number of extra inputs to include for untraceability. Multiple payments can be made at once by adding <address_2> <amount_2> etcetera (before the payment ID, if it's included)")); m_cmd_binder.set_handler("locked_transfer", boost::bind(&simple_wallet::locked_transfer, this, _1), tr("locked_transfer [<mixin_count>] <addr> <amount> <lockblocks>(Number of blocks to lock the transaction for, max 1000000) [<payment_id>]")); m_cmd_binder.set_handler("sweep_unmixable", boost::bind(&simple_wallet::sweep_unmixable, this, _1), tr("Send all unmixable outputs to yourself with mixin 0")); m_cmd_binder.set_handler("sweep_all", boost::bind(&simple_wallet::sweep_all, this, _1), tr("sweep_all [mixin] address [payment_id] - Send all unlocked balance to an address")); @@ -744,6 +739,21 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args) } else { + +#define CHECK_SIMPLE_VARIABLE(name, f, help) do \ + if (args[0] == name) { \ + if (args.size() <= 1) \ + { \ + fail_msg_writer() << "set " << #name << ": " << tr("needs an argument") << " (" << help << ")"; \ + return true; \ + } \ + else \ + { \ + f(args); \ + return true; \ + } \ + } while(0) + if (args[0] == "seed") { if (args.size() == 1) @@ -757,176 +767,19 @@ bool simple_wallet::set_variable(const std::vector<std::string> &args) return true; } } - else if (args[0] == "always-confirm-transfers") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set always-confirm-transfers: needs an argument (0 or 1)"); - return true; - } - else - { - set_always_confirm_transfers(args); - return true; - } - } - else if (args[0] == "print-ring-members") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set print-ring-members: needs an argument (0 or 1)"); - return true; - } - else - { - set_print_ring_members(args); - return true; - } - } - else if (args[0] == "store-tx-info") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set store-tx-info: needs an argument (0 or 1)"); - return true; - } - else - { - set_store_tx_info(args); - return true; - } - } - else if (args[0] == "default-mixin") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set default-mixin: needs an argument (integer >= 2)"); - return true; - } - else - { - set_default_mixin(args); - return true; - } - } - else if (args[0] == "auto-refresh") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set auto-refresh: needs an argument (0 or 1)"); - return true; - } - else - { - set_auto_refresh(args); - return true; - } - } - else if (args[0] == "refresh-type") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set refresh-type: needs an argument:") << - 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)"); - return true; - } - else - { - set_refresh_type(args); - return true; - } - } - else if (args[0] == "priority") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set priority: needs an argument: 0, 1, 2, 3, or 4"); - return true; - } - else - { - set_default_priority(args); - return true; - } - } - else if (args[0] == "confirm-missing-payment-id") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set confirm-missing-payment-id: needs an argument (0 or 1)"); - return true; - } - else - { - set_confirm_missing_payment_id(args); - return true; - } - } - else if (args[0] == "ask-password") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set ask-password: needs an argument (0 or 1)"); - return true; - } - else - { - set_ask_password(args); - return true; - } - } - else if (args[0] == "unit") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set unit: needs an argument (monero, millinero, micronero, nanop, piconero)"); - return true; - } - else - { - set_unit(args); - return true; - } - } - else if (args[0] == "min-outputs-count") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set min-outputs-count: needs an argument (unsigned integer)"); - return true; - } - else - { - set_min_output_count(args); - return true; - } - } - else if (args[0] == "min-outputs-value") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set min-outputs-value: needs an argument (unsigned integer)"); - return true; - } - else - { - set_min_output_value(args); - return true; - } - } - else if (args[0] == "merge-destinations") - { - if (args.size() <= 1) - { - fail_msg_writer() << tr("set merge-destinations: needs an argument (0 or 1)"); - return true; - } - else - { - set_merge_destinations(args); - return true; - } - } + 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-mixin", set_default_mixin, tr("integer >= 2")); + 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")); + CHECK_SIMPLE_VARIABLE("confirm-missing-payment-id", set_confirm_missing_payment_id, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("ask-password", set_ask_password, tr("0 or 1")); + CHECK_SIMPLE_VARIABLE("unit", set_unit, tr("monero, millinero, micronero, nanop, piconero")); + CHECK_SIMPLE_VARIABLE("min-outputs-count", set_min_output_count, tr("unsigned integer")); + CHECK_SIMPLE_VARIABLE("min-outputs-value", set_min_output_value, tr("amount")); + CHECK_SIMPLE_VARIABLE("merge-destinations", set_merge_destinations, tr("0 or 1")); } fail_msg_writer() << tr("set: unrecognized argument(s)"); return true; @@ -2205,6 +2058,18 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri std::vector<std::string> local_args = args_; + int priority = 0; + if(local_args.size() > 0) { + auto priority_pos = std::find( + allowed_priority_strings.begin(), + allowed_priority_strings.end(), + local_args[0]); + if(priority_pos != allowed_priority_strings.end()) { + local_args.erase(local_args.begin()); + priority = std::distance(allowed_priority_strings.begin(), priority_pos); + } + } + size_t fake_outs_count; if(local_args.size() > 0) { if(!epee::string_tools::get_xtype_from_string(fake_outs_count, local_args[0])) @@ -2356,15 +2221,15 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri return true; } unlock_block = bc_height + locked_blocks; - ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, unlock_block /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon); + ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_trusted_daemon); break; case TransferNew: - ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon); + ptx_vector = m_wallet->create_transactions_2(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_trusted_daemon); break; default: LOG_ERROR("Unknown transfer method, using original"); case TransferOriginal: - ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, 0 /* unused fee arg*/, extra, m_trusted_daemon); + ptx_vector = m_wallet->create_transactions(dsts, fake_outs_count, 0 /* unlock_time */, priority, extra, m_trusted_daemon); break; } @@ -2993,7 +2858,6 @@ bool simple_wallet::sweep_all(const std::vector<std::string> &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::donate(const std::vector<std::string> &args_) { - if (m_wallet->ask_password() && !get_and_verify_password()) { return true; } std::vector<std::string> local_args = args_; if(local_args.empty() || local_args.size() > 3) { @@ -3041,6 +2905,7 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes, size_t min_mixin = ~0; std::unordered_map<std::string, uint64_t> dests; const std::string wallet_address = m_wallet->get_account().get_public_address_str(m_wallet->testnet()); + int first_known_non_zero_change_index = -1; for (size_t n = 0; n < get_num_txes(); ++n) { const tools::wallet2::tx_construction_data &cd = get_tx(n); @@ -3075,10 +2940,15 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes, fail_msg_writer() << tr("Claimed change is larger than payment to the change address"); return false; } - if (memcmp(&cd.change_dts.addr, &get_tx(0).change_dts.addr, sizeof(cd.change_dts.addr))) + if (cd.change_dts.amount > 0) { - fail_msg_writer() << tr("Change does to more than one address"); - return false; + if (first_known_non_zero_change_index == -1) + first_known_non_zero_change_index = n; + if (memcmp(&cd.change_dts.addr, &get_tx(first_known_non_zero_change_index).change_dts.addr, sizeof(cd.change_dts.addr))) + { + fail_msg_writer() << tr("Change goes to more than one address"); + return false; + } } change += cd.change_dts.amount; it->second -= cd.change_dts.amount; |