From cb0b559451466112332e0c251d100c2322803ad7 Mon Sep 17 00:00:00 2001 From: moneromooo-monero Date: Thu, 27 Jul 2017 11:28:53 +0100 Subject: [PATCH] Move OpenAlias console input back from libs Library code should definitely not ask for console input unless it's clearly an input function. Delegating the user interaction part to the caller means it can now be used by a GUI, or have a decision algorithm better adapted to a particular caller. --- src/common/dns_utils.cpp | 46 +--------------- src/common/dns_utils.h | 2 +- .../cryptonote_basic_impl.cpp | 8 +-- src/cryptonote_basic/cryptonote_basic_impl.h | 13 ++++- src/daemon/command_parser_executor.cpp | 3 +- src/simplewallet/simplewallet.cpp | 50 ++++++++++++++--- src/wallet/wallet_rpc_server.cpp | 55 +++++++++++++++++-- 7 files changed, 113 insertions(+), 64 deletions(-) diff --git a/src/common/dns_utils.cpp b/src/common/dns_utils.cpp index ab38cbbae..b3b464e92 100644 --- a/src/common/dns_utils.cpp +++ b/src/common/dns_utils.cpp @@ -26,12 +26,9 @@ // 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. -#include "common/command_line.h" -#include "common/i18n.h" #include "common/dns_utils.h" +#include "common/i18n.h" #include "cryptonote_basic/cryptonote_basic_impl.h" -#include -#include // check local first (in the event of static or in-source compilation of libunbound) #include "unbound.h" @@ -405,7 +402,7 @@ std::vector addresses_from_url(const std::string& url, bool& dnssec return addresses; } -std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid, bool cli_confirm) +std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid, std::function&, bool)> dns_confirm) { // attempt to get address from dns query auto addresses = addresses_from_url(url, dnssec_valid); @@ -414,44 +411,7 @@ std::string get_account_address_as_str_from_url(const std::string& url, bool& dn LOG_ERROR("wrong address: " << url); return {}; } - // for now, move on only if one address found - if (addresses.size() > 1) - { - LOG_ERROR("not yet supported: Multiple Monero addresses found for given URL: " << url); - return {}; - } - if (!cli_confirm) - return addresses[0]; - // prompt user for confirmation. - // inform user of DNSSEC validation status as well. - std::string dnssec_str; - if (dnssec_valid) - { - dnssec_str = tr("DNSSEC validation passed"); - } - else - { - dnssec_str = tr("WARNING: DNSSEC validation was unsuccessful, this address may not be correct!"); - } - std::stringstream prompt; - prompt << tr("For URL: ") << url - << ", " << dnssec_str << std::endl - << tr(" Monero Address = ") << addresses[0] - << std::endl - << tr("Is this OK? (Y/n) ") - ; - // prompt the user for confirmation given the dns query and dnssec status - std::string confirm_dns_ok = command_line::input_line(prompt.str()); - if (std::cin.eof()) - { - return {}; - } - if (!command_line::is_yes(confirm_dns_ok)) - { - std::cout << tr("you have cancelled the transfer request") << std::endl; - return {}; - } - return addresses[0]; + return dns_confirm(url, addresses, dnssec_valid); } namespace diff --git a/src/common/dns_utils.h b/src/common/dns_utils.h index 53c0c1c7b..1f5cb4e7f 100644 --- a/src/common/dns_utils.h +++ b/src/common/dns_utils.h @@ -163,7 +163,7 @@ namespace dns_utils std::string address_from_txt_record(const std::string& s); std::vector addresses_from_url(const std::string& url, bool& dnssec_valid); -std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid, bool cli_confirm = true); +std::string get_account_address_as_str_from_url(const std::string& url, bool& dnssec_valid, std::function&, bool)> confirm_dns); bool load_txt_records_from_dns(std::vector &records, const std::vector &dns_urls); diff --git a/src/cryptonote_basic/cryptonote_basic_impl.cpp b/src/cryptonote_basic/cryptonote_basic_impl.cpp index edd67793f..a59f96956 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.cpp +++ b/src/cryptonote_basic/cryptonote_basic_impl.cpp @@ -308,13 +308,13 @@ namespace cryptonote { , crypto::hash8& payment_id , bool testnet , const std::string& str_or_url - , bool cli_confirm + , std::function&, bool)> dns_confirm ) { if (get_account_integrated_address_from_str(address, has_payment_id, payment_id, testnet, str_or_url)) return true; bool dnssec_valid; - std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(str_or_url, dnssec_valid, cli_confirm); + std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(str_or_url, dnssec_valid, dns_confirm); return !address_str.empty() && get_account_integrated_address_from_str(address, has_payment_id, payment_id, testnet, address_str); } @@ -323,12 +323,12 @@ namespace cryptonote { cryptonote::account_public_address& address , bool testnet , const std::string& str_or_url - , bool cli_confirm + , std::function&, bool)> dns_confirm ) { bool has_payment_id; crypto::hash8 payment_id; - return get_account_address_from_str_or_url(address, has_payment_id, payment_id, testnet, str_or_url, cli_confirm); + return get_account_address_from_str_or_url(address, has_payment_id, payment_id, testnet, str_or_url, dns_confirm); } //-------------------------------------------------------------------------------- bool operator ==(const cryptonote::transaction& a, const cryptonote::transaction& b) { diff --git a/src/cryptonote_basic/cryptonote_basic_impl.h b/src/cryptonote_basic/cryptonote_basic_impl.h index 14c03ac4c..9838fcb47 100644 --- a/src/cryptonote_basic/cryptonote_basic_impl.h +++ b/src/cryptonote_basic/cryptonote_basic_impl.h @@ -67,6 +67,15 @@ namespace cryptonote { }; #pragma pack (pop) + namespace + { + std::string return_first_address(const std::string &url, const std::vector &addresses, bool dnssec_valid) + { + if (addresses.empty()) + return {}; + return addresses[0]; + } + } /************************************************************************/ /* Cryptonote helper functions */ @@ -109,14 +118,14 @@ namespace cryptonote { , crypto::hash8& payment_id , bool testnet , const std::string& str_or_url - , bool cli_confirm = true + , std::function&, bool)> dns_confirm = return_first_address ); bool get_account_address_from_str_or_url( cryptonote::account_public_address& address , bool testnet , const std::string& str_or_url - , bool cli_confirm = true + , std::function&, bool)> dns_confirm = return_first_address ); bool is_coinbase(const transaction& tx); diff --git a/src/daemon/command_parser_executor.cpp b/src/daemon/command_parser_executor.cpp index a7caeeffc..d654954ef 100644 --- a/src/daemon/command_parser_executor.cpp +++ b/src/daemon/command_parser_executor.cpp @@ -256,7 +256,8 @@ bool t_command_parser_executor::start_mining(const std::vector& arg if(!cryptonote::get_account_integrated_address_from_str(adr, has_payment_id, payment_id, true, args.front())) { bool dnssec_valid; - std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(args.front(), dnssec_valid); + std::string address_str = tools::dns_utils::get_account_address_as_str_from_url(args.front(), dnssec_valid, + [](const std::string &url, const std::vector &addresses, bool dnssec_valid){return addresses[0];}); if(!cryptonote::get_account_integrated_address_from_str(adr, has_payment_id, payment_id, false, address_str)) { if(!cryptonote::get_account_integrated_address_from_str(adr, has_payment_id, payment_id, true, address_str)) diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp index adf2fde80..c132db196 100644 --- a/src/simplewallet/simplewallet.cpp +++ b/src/simplewallet/simplewallet.cpp @@ -281,6 +281,42 @@ namespace { return boost::lexical_cast(version >> 16) + "." + boost::lexical_cast(version & 0xffff); } + + std::string oa_prompter(const std::string &url, const std::vector &addresses, bool dnssec_valid) + { + if (addresses.empty()) + return {}; + // prompt user for confirmation. + // inform user of DNSSEC validation status as well. + std::string dnssec_str; + if (dnssec_valid) + { + dnssec_str = tr("DNSSEC validation passed"); + } + else + { + dnssec_str = tr("WARNING: DNSSEC validation was unsuccessful, this address may not be correct!"); + } + std::stringstream prompt; + prompt << tr("For URL: ") << url + << ", " << dnssec_str << std::endl + << tr(" Monero Address = ") << addresses[0] + << std::endl + << tr("Is this OK? (Y/n) ") + ; + // prompt the user for confirmation given the dns query and dnssec status + std::string confirm_dns_ok = command_line::input_line(prompt.str()); + if (std::cin.eof()) + { + return {}; + } + if (!command_line::is_yes(confirm_dns_ok)) + { + std::cout << tr("you have cancelled the transfer request") << std::endl; + return {}; + } + return addresses[0]; + } } @@ -2215,7 +2251,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vectortestnet(), local_args[i])) + if (!cryptonote::get_account_address_from_str_or_url(de.addr, has_payment_id, new_payment_id, m_wallet->testnet(), local_args[i], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -2713,7 +2749,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector &a bool has_payment_id; crypto::hash8 new_payment_id; cryptonote::account_public_address address; - if (!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, new_payment_id, m_wallet->testnet(), local_args[0])) + if (!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, new_payment_id, m_wallet->testnet(), local_args[0], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -3273,7 +3309,7 @@ bool simple_wallet::get_tx_proof(const std::vector &args) cryptonote::account_public_address address; bool has_payment_id; crypto::hash8 payment_id; - if(!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, payment_id, m_wallet->testnet(), args[1])) + if(!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, payment_id, m_wallet->testnet(), args[1], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -3375,7 +3411,7 @@ bool simple_wallet::check_tx_key(const std::vector &args_) cryptonote::account_public_address address; bool has_payment_id; crypto::hash8 payment_id; - if(!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, payment_id, m_wallet->testnet(), local_args[2])) + if(!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, payment_id, m_wallet->testnet(), local_args[2], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -3527,7 +3563,7 @@ bool simple_wallet::check_tx_proof(const std::vector &args) cryptonote::account_public_address address; bool has_payment_id; crypto::hash8 payment_id; - if(!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, payment_id, m_wallet->testnet(), args[1])) + if(!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, payment_id, m_wallet->testnet(), args[1], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -4045,7 +4081,7 @@ bool simple_wallet::address_book(const std::vector &args/* = std::v cryptonote::account_public_address address; bool has_payment_id; crypto::hash8 payment_id8; - if(!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, payment_id8, m_wallet->testnet(), args[1])) + if(!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, payment_id8, m_wallet->testnet(), args[1], oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; @@ -4236,7 +4272,7 @@ bool simple_wallet::verify(const std::vector &args) cryptonote::account_public_address address; bool has_payment_id; crypto::hash8 payment_id; - if(!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, payment_id, m_wallet->testnet(), address_string)) + if(!cryptonote::get_account_address_from_str_or_url(address, has_payment_id, payment_id, m_wallet->testnet(), address_string, oa_prompter)) { fail_msg_writer() << tr("failed to parse address"); return true; diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index e7b9b5a71..164b3d251 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -352,10 +352,25 @@ namespace tools cryptonote::tx_destination_entry de; bool has_payment_id; crypto::hash8 new_payment_id; - if(!get_account_address_from_str_or_url(de.addr, has_payment_id, new_payment_id, m_wallet->testnet(), it->address, false)) + er.message = ""; + if(!get_account_address_from_str_or_url(de.addr, has_payment_id, new_payment_id, m_wallet->testnet(), it->address, + [&er](const std::string &url, const std::vector &addresses, bool dnssec_valid)->std::string { + if (!dnssec_valid) + { + er.message = std::string("Invalid DNSSEC for ") + url; + return {}; + } + if (addresses.empty()) + { + er.message = std::string("No Monero address found at ") + url; + return {}; + } + return addresses[0]; + })) { er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; - er.message = std::string("WALLET_RPC_ERROR_CODE_WRONG_ADDRESS: ") + it->address; + if (er.message.empty()) + er.message = std::string("WALLET_RPC_ERROR_CODE_WRONG_ADDRESS: ") + it->address; return false; } de.amount = it->amount; @@ -1018,10 +1033,23 @@ namespace tools cryptonote::account_public_address address; bool has_payment_id; crypto::hash8 payment_id; - if(!get_account_address_from_str_or_url(address, has_payment_id, payment_id, m_wallet->testnet(), req.address, false)) + er.message = ""; + if(!get_account_address_from_str_or_url(address, has_payment_id, payment_id, m_wallet->testnet(), req.address, + [&er](const std::string &url, const std::vector &addresses, bool dnssec_valid)->std::string { + if (!dnssec_valid) + { + er.message = std::string("Invalid DNSSEC for ") + url; + return {}; + } + if (addresses.empty()) + { + er.message = std::string("No Monero address found at ") + url; + return {}; + } + return addresses[0]; + })) { er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; - er.message = ""; return false; } @@ -1412,10 +1440,25 @@ namespace tools bool has_payment_id; crypto::hash8 payment_id8; crypto::hash payment_id = cryptonote::null_hash; - if(!get_account_address_from_str_or_url(address, has_payment_id, payment_id8, m_wallet->testnet(), req.address, false)) + er.message = ""; + if(!get_account_address_from_str_or_url(address, has_payment_id, payment_id8, m_wallet->testnet(), req.address, + [&er](const std::string &url, const std::vector &addresses, bool dnssec_valid)->std::string { + if (!dnssec_valid) + { + er.message = std::string("Invalid DNSSEC for ") + url; + return {}; + } + if (addresses.empty()) + { + er.message = std::string("No Monero address found at ") + url; + return {}; + } + return addresses[0]; + })) { er.code = WALLET_RPC_ERROR_CODE_WRONG_ADDRESS; - er.message = std::string("WALLET_RPC_ERROR_CODE_WRONG_ADDRESS: ") + req.address; + if (er.message.empty()) + er.message = std::string("WALLET_RPC_ERROR_CODE_WRONG_ADDRESS: ") + req.address; return false; } if (has_payment_id)