diff options
Diffstat (limited to 'src/simplewallet')
-rw-r--r-- | src/simplewallet/simplewallet.cpp | 125 | ||||
-rw-r--r-- | src/simplewallet/simplewallet.h | 3 |
2 files changed, 102 insertions, 26 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index 43e8cb72f..ff81aea62 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -628,7 +628,7 @@ bool simple_wallet::print_seed(bool encrypted) epee::wipeable_string seed_pass; if (encrypted) { - auto pwd_container = password_prompter(tr("Enter optional seed encryption passphrase, empty to see raw seed"), true); + auto pwd_container = password_prompter(tr("Enter optional seed offset passphrase, empty to see raw seed"), true); if (std::cin.eof() || !pwd_container) return true; seed_pass = pwd_container->password(); @@ -1825,6 +1825,7 @@ bool simple_wallet::set_auto_refresh(const std::vector<std::string> &args/* = st if (pwd_container) { parse_bool_and_use(args[1], [&](bool auto_refresh) { + m_auto_refresh_enabled.store(false, std::memory_order_relaxed); m_wallet->auto_refresh(auto_refresh); m_idle_mutex.lock(); m_auto_refresh_enabled.store(auto_refresh, std::memory_order_relaxed); @@ -2169,6 +2170,10 @@ simple_wallet::simple_wallet() boost::bind(&simple_wallet::locked_transfer, this, _1), tr("locked_transfer [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <addr> <amount> <lockblocks> [<payment_id>]"), tr("Transfer <amount> to <address> and lock it for <lockblocks> (max. 1000000). If the parameter \"index=<N1>[,<N2>,...]\" is specified, the wallet uses outputs received by addresses of those indices. If omitted, the wallet randomly chooses address indices to be used. In any case, it tries its best not to combine outputs across multiple addresses. <priority> is the priority of the transaction. The higher the priority, the higher the transaction fee. 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. <ring_size> is the number of 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_sweep_all", + boost::bind(&simple_wallet::locked_sweep_all, this, _1), + tr("locked_sweep_all [index=<N1>[,<N2>,...]] [<priority>] [<ring_size>] <address> <lockblocks> [<payment_id>]"), + tr("Send all unlocked balance to an address and lock it for <lockblocks> (max. 1000000). If the parameter \"index<N1>[,<N2>,...]\" is specified, the wallet sweeps outputs received by those address indices. If omitted, the wallet randomly chooses an address index to be used. <priority> is the priority of the sweep. The higher the priority, the higher the transaction fee. 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. <ring_size> is the number of inputs to include for untraceability.")); m_cmd_binder.set_handler("sweep_unmixable", boost::bind(&simple_wallet::sweep_unmixable, this, _1), tr("Send all unmixable outputs to yourself with ring_size 1")); @@ -2334,7 +2339,7 @@ simple_wallet::simple_wallet() tr("Check a signature proving that the owner of <address> holds at least this much, optionally with a challenge string <message>.")); m_cmd_binder.set_handler("show_transfers", boost::bind(&simple_wallet::show_transfers, this, _1), - tr("show_transfers [in|out|pending|failed|pool] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]]"), + tr("show_transfers [in|out|pending|failed|pool|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]]"), tr("Show the incoming/outgoing transfers within an optional height range.")); m_cmd_binder.set_handler("unspent_outputs", boost::bind(&simple_wallet::unspent_outputs, this, _1), @@ -2793,7 +2798,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm) } } - auto pwd_container = password_prompter(tr("Enter seed encryption passphrase, empty if none"), false); + auto pwd_container = password_prompter(tr("Enter seed offset passphrase, empty if none"), false); if (std::cin.eof() || !pwd_container) return false; epee::wipeable_string seed_pass = pwd_container->password(); @@ -3348,14 +3353,16 @@ bool simple_wallet::try_connect_to_daemon(bool silent, uint32_t* version) */ std::string simple_wallet::get_mnemonic_language() { - std::vector<std::string> language_list; + std::vector<std::string> language_list_self, language_list_english; + const std::vector<std::string> &language_list = m_use_english_language_names ? language_list_english : language_list_self; std::string language_choice; int language_number = -1; - crypto::ElectrumWords::get_language_list(language_list, m_use_english_language_names); + crypto::ElectrumWords::get_language_list(language_list_self, false); + crypto::ElectrumWords::get_language_list(language_list_english, true); std::cout << tr("List of available languages for your wallet's seed:") << std::endl; std::cout << tr("If your display freezes, exit blind with ^C, then run again with --use-english-language-names") << std::endl; int ii; - std::vector<std::string>::iterator it; + std::vector<std::string>::const_iterator it; for (it = language_list.begin(), ii = 0; it != language_list.end(); it++, ii++) { std::cout << ii << " : " << *it << std::endl; @@ -3379,7 +3386,7 @@ std::string simple_wallet::get_mnemonic_language() fail_msg_writer() << tr("invalid language choice entered. Please try again.\n"); } } - return language_list[language_number]; + return language_list_self[language_number]; } //---------------------------------------------------------------------------------------------------- boost::optional<tools::password_container> simple_wallet::get_and_verify_password() const @@ -3973,6 +3980,24 @@ void simple_wallet::on_money_received(uint64_t height, const crypto::hash &txid, tr("txid ") << txid << ", " << print_money(amount) << ", " << tr("idx ") << subaddr_index; + + const uint64_t warn_height = m_wallet->nettype() == TESTNET ? 1000000 : m_wallet->nettype() == STAGENET ? 50000 : 1650000; + if (height >= warn_height) + { + std::vector<tx_extra_field> tx_extra_fields; + parse_tx_extra(tx.extra, tx_extra_fields); // failure ok + tx_extra_nonce extra_nonce; + if (find_tx_extra_field_by_type(tx_extra_fields, extra_nonce)) + { + crypto::hash8 payment_id8 = crypto::null_hash8; + if (get_encrypted_payment_id_from_tx_extra_nonce(extra_nonce.nonce, payment_id8)) + message_writer() << + tr("NOTE: this transaction uses an encrypted payment ID: consider using subaddresses instead"); + else + message_writer(console_color_red, false) << + tr("WARNING: this transaction uses an unencrypted payment ID: consider using subaddresses instead"); + } + } if (m_auto_refresh_refreshing) m_cmd_binder.print_prompt(); else @@ -4566,6 +4591,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri return true; } payment_id_seen = true; + message_writer() << tr("Unencrypted payment IDs are bad for privacy: ask the recipient to use subaddresses instead"); } uint64_t locked_blocks = 0; @@ -4874,6 +4900,11 @@ bool simple_wallet::locked_transfer(const std::vector<std::string> &args_) return transfer_main(TransferLocked, args_); } //---------------------------------------------------------------------------------------------------- +bool simple_wallet::locked_sweep_all(const std::vector<std::string> &args_) +{ + return sweep_main(0, true, args_); +} +//---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_) { @@ -4981,7 +5012,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_) return true; } //---------------------------------------------------------------------------------------------------- -bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &args_) +bool simple_wallet::sweep_main(uint64_t below, bool locked, const std::vector<std::string> &args_) { auto print_usage = [below]() { @@ -5044,9 +5075,44 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a return true; } + uint64_t unlock_block = 0; + if (locked) { + uint64_t locked_blocks = 0; + + if (local_args.size() < 2) { + fail_msg_writer() << tr("missing lockedblocks parameter"); + return true; + } + + try + { + locked_blocks = boost::lexical_cast<uint64_t>(local_args[1]); + } + catch (const std::exception &e) + { + fail_msg_writer() << tr("bad locked_blocks parameter"); + return true; + } + if (locked_blocks > 1000000) + { + fail_msg_writer() << tr("Locked blocks too high, max 1000000 (˜4 yrs)"); + return true; + } + std::string err; + uint64_t bc_height = get_daemon_blockchain_height(err); + if (!err.empty()) + { + fail_msg_writer() << tr("failed to get blockchain height: ") << err; + return true; + } + unlock_block = bc_height + locked_blocks; + + local_args.erase(local_args.begin() + 1); + } + std::vector<uint8_t> extra; bool payment_id_seen = false; - if (2 >= local_args.size()) + if (local_args.size() >= 2) { std::string payment_id_str = local_args.back(); @@ -5128,7 +5194,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a try { // figure out what tx will be necessary - auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, 0 /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, is_daemon_trusted()); + auto ptx_vector = m_wallet->create_transactions_all(below, info.address, info.is_subaddress, fake_outs_count, unlock_block /* unlock_time */, priority, extra, m_current_subaddress_account, subaddr_indices, is_daemon_trusted()); if (ptx_vector.empty()) { @@ -5424,7 +5490,7 @@ bool simple_wallet::sweep_single(const std::vector<std::string> &args_) //---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_all(const std::vector<std::string> &args_) { - return sweep_main(0, args_); + return sweep_main(0, false, args_); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::sweep_below(const std::vector<std::string> &args_) @@ -5440,7 +5506,7 @@ bool simple_wallet::sweep_below(const std::vector<std::string> &args_) fail_msg_writer() << tr("invalid amount threshold"); return true; } - return sweep_main(below, std::vector<std::string>(++args_.begin(), args_.end())); + return sweep_main(below, false, std::vector<std::string>(++args_.begin(), args_.end())); } //---------------------------------------------------------------------------------------------------- bool simple_wallet::donate(const std::vector<std::string> &args_) @@ -6279,12 +6345,13 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_) bool pending = true; bool failed = true; bool pool = true; + bool coinbase = true; uint64_t min_height = 0; uint64_t max_height = (uint64_t)-1; boost::optional<uint32_t> subaddr_index; if(local_args.size() > 4) { - fail_msg_writer() << tr("usage: show_transfers [in|out|all|pending|failed] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]]"); + fail_msg_writer() << tr("usage: show_transfers [in|out|all|pending|failed|coinbase] [index=<N1>[,<N2>,...]] [<min_height> [<max_height>]]"); return true; } @@ -6297,19 +6364,24 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_) local_args.erase(local_args.begin()); } else if (local_args[0] == "out" || local_args[0] == "outgoing") { - in = pool = false; + in = pool = coinbase = false; local_args.erase(local_args.begin()); } else if (local_args[0] == "pending") { - in = out = failed = false; + in = out = failed = coinbase = false; local_args.erase(local_args.begin()); } else if (local_args[0] == "failed") { - in = out = pending = pool = false; + in = out = pending = pool = coinbase = false; local_args.erase(local_args.begin()); } else if (local_args[0] == "pool") { - in = out = pending = failed = false; + in = out = pending = failed = coinbase = false; + local_args.erase(local_args.begin()); + } + else if (local_args[0] == "coinbase") { + in = out = pending = failed = pool = false; + coinbase = true; local_args.erase(local_args.begin()); } else if (local_args[0] == "all" || local_args[0] == "both") { @@ -6350,20 +6422,23 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_) local_args.erase(local_args.begin()); } - std::multimap<uint64_t, std::pair<bool,std::string>> output; + std::multimap<uint64_t, std::tuple<epee::console_colors, std::string, std::string>> output; PAUSE_READLINE(); - if (in) { + if (in || coinbase) { std::list<std::pair<crypto::hash, tools::wallet2::payment_details>> payments; m_wallet->get_payments(payments, min_height, max_height, m_current_subaddress_account, subaddr_indices); for (std::list<std::pair<crypto::hash, tools::wallet2::payment_details>>::const_iterator i = payments.begin(); i != payments.end(); ++i) { const tools::wallet2::payment_details &pd = i->second; + if (!pd.m_coinbase && !in) + continue; std::string payment_id = string_tools::pod_to_hex(i->first); if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0,16); std::string note = m_wallet->get_tx_note(pd.m_tx_hash); - output.insert(std::make_pair(pd.m_block_height, std::make_pair(true, (boost::format("%25.25s %20.20s %s %s %d %s %s") % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % pd.m_subaddr_index.minor % "-" % note).str()))); + const std::string type = pd.m_coinbase ? tr("block") : tr("in"); + output.insert(std::make_pair(pd.m_block_height, std::make_tuple(epee::console_color_green, type, (boost::format("%25.25s %20.20s %s %s %d %s %s") % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount) % string_tools::pod_to_hex(pd.m_tx_hash) % payment_id % pd.m_subaddr_index.minor % "-" % note).str()))); } } @@ -6396,15 +6471,15 @@ bool simple_wallet::show_transfers(const std::vector<std::string> &args_) if (payment_id.substr(16).find_first_not_of('0') == std::string::npos) payment_id = payment_id.substr(0,16); std::string note = m_wallet->get_tx_note(i->first); - output.insert(std::make_pair(pd.m_block_height, std::make_pair(false, (boost::format("%25.25s %20.20s %s %s %14.14s %s %s - %s") % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount_in - change - fee) % string_tools::pod_to_hex(i->first) % payment_id % print_money(fee) % dests % print_subaddr_indices(pd.m_subaddr_indices) % note).str()))); + output.insert(std::make_pair(pd.m_block_height, std::make_tuple(epee::console_color_magenta, tr("out"), (boost::format("%25.25s %20.20s %s %s %14.14s %s %s - %s") % get_human_readable_timestamp(pd.m_timestamp) % print_money(pd.m_amount_in - change - fee) % string_tools::pod_to_hex(i->first) % payment_id % print_money(fee) % dests % print_subaddr_indices(pd.m_subaddr_indices) % note).str()))); } } // print in and out sorted by height - for (std::map<uint64_t, std::pair<bool, std::string>>::const_iterator i = output.begin(); i != output.end(); ++i) { - message_writer(i->second.first ? console_color_green : console_color_magenta, false) << + for (std::multimap<uint64_t, std::tuple<epee::console_colors, std::string, std::string>>::const_iterator i = output.begin(); i != output.end(); ++i) { + message_writer(std::get<0>(i->second), false) << boost::format("%8.8llu %6.6s %s") % - ((unsigned long long)i->first) % (i->second.first ? tr("in") : tr("out")) % i->second.second; + ((unsigned long long)i->first) % std::get<1>(i->second) % std::get<2>(i->second); } if (pool) { @@ -6463,7 +6538,7 @@ bool simple_wallet::unspent_outputs(const std::vector<std::string> &args_) auto local_args = args_; std::set<uint32_t> subaddr_indices; - if (local_args.size() > 0 && local_args[0].substr(0, 6) != "index=") + if (local_args.size() > 0 && local_args[0].substr(0, 6) == "index=") { if (!parse_subaddress_indices(local_args[0], subaddr_indices)) return true; diff --git a/src/simplewallet/simplewallet.h b/src/simplewallet/simplewallet.h index e78cdcc31..e08f31607 100644 --- a/src/simplewallet/simplewallet.h +++ b/src/simplewallet/simplewallet.h @@ -153,7 +153,8 @@ namespace cryptonote bool transfer(const std::vector<std::string> &args); bool transfer_new(const std::vector<std::string> &args); bool locked_transfer(const std::vector<std::string> &args); - bool sweep_main(uint64_t below, const std::vector<std::string> &args); + bool locked_sweep_all(const std::vector<std::string> &args); + bool sweep_main(uint64_t below, bool locked, const std::vector<std::string> &args); bool sweep_all(const std::vector<std::string> &args); bool sweep_below(const std::vector<std::string> &args); bool sweep_single(const std::vector<std::string> &args); |