aboutsummaryrefslogtreecommitdiff
path: root/src/simplewallet/simplewallet.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/simplewallet/simplewallet.cpp')
-rw-r--r--src/simplewallet/simplewallet.cpp154
1 files changed, 113 insertions, 41 deletions
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index 04170df62..aa571755f 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -58,6 +58,7 @@
#include "crypto/crypto.h" // for crypto::secret_key definition
#include "mnemonics/electrum-words.h"
#include "rapidjson/document.h"
+#include "common/json_util.h"
#include <stdexcept>
#if defined(WIN32)
@@ -257,6 +258,8 @@ bool simple_wallet::seed(const std::vector<std::string> &args/* = std::vector<st
if (m_wallet->get_seed_language().empty())
{
std::string mnemonic_language = get_mnemonic_language();
+ if (mnemonic_language.empty())
+ return true;
m_wallet->set_seed_language(mnemonic_language);
}
@@ -304,6 +307,8 @@ bool simple_wallet::seed_set_language(const std::vector<std::string> &args/* = s
}
std::string mnemonic_language = get_mnemonic_language();
+ if (mnemonic_language.empty())
+ return true;
m_wallet->set_seed_language(mnemonic_language);
m_wallet->rewrite(m_wallet_file, pwd_container.password());
return true;
@@ -698,6 +703,10 @@ bool simple_wallet::ask_wallet_create_if_needed()
tr("Specify wallet file name (e.g., MyWallet). If the wallet doesn't exist, it will be created.\n"
"Wallet file name: ")
);
+ if (std::cin.eof())
+ {
+ return false;
+ }
valid_path = tools::wallet2::wallet_valid_path_format(wallet_path);
if (!valid_path)
{
@@ -833,40 +842,27 @@ bool simple_wallet::generate_from_json(const boost::program_options::variables_m
return false;
}
- if (!json.HasMember("version")) {
- fail_msg_writer() << tr("Version not found in JSON");
- return false;
- }
- unsigned int version = json["version"].GetUint();
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, version, unsigned, Uint, true);
const int current_version = 1;
- if (version > current_version) {
- fail_msg_writer() << boost::format(tr("Version %u too new, we can only grok up to %u")) % version % current_version;
+ if (field_version > current_version) {
+ fail_msg_writer() << boost::format(tr("Version %u too new, we can only grok up to %u")) % field_version % current_version;
return false;
}
- if (!json.HasMember("filename")) {
- fail_msg_writer() << tr("Filename not found in JSON");
- return false;
- }
- std::string filename = json["filename"].GetString();
- bool recover = false;
- uint64_t scan_from_height = 0;
- if (json.HasMember("scan_from_height")) {
- scan_from_height = json["scan_from_height"].GetUint64();
- recover = true;
- }
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, filename, std::string, String, true);
- password = "";
- if (json.HasMember("password")) {
- password = json["password"].GetString();
- }
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, scan_from_height, uint64_t, Uint64, false);
+ bool recover = field_scan_from_height_found;
+
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, password, std::string, String, false);
+ password = field_password;
- std::string viewkey_string("");
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, viewkey, std::string, String, false);
crypto::secret_key viewkey;
- if (json.HasMember("viewkey")) {
- viewkey_string = json["viewkey"].GetString();
+ if (field_viewkey_found)
+ {
cryptonote::blobdata viewkey_data;
- if(!epee::string_tools::parse_hexstr_to_binbuff(viewkey_string, viewkey_data))
+ if(!epee::string_tools::parse_hexstr_to_binbuff(field_viewkey, viewkey_data))
{
fail_msg_writer() << tr("failed to parse view key secret key");
return false;
@@ -874,12 +870,12 @@ bool simple_wallet::generate_from_json(const boost::program_options::variables_m
viewkey = *reinterpret_cast<const crypto::secret_key*>(viewkey_data.data());
}
- std::string spendkey_string("");
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, spendkey, std::string, String, false);
crypto::secret_key spendkey;
- if (json.HasMember("spendkey")) {
- spendkey_string = json["spendkey"].GetString();
+ if (field_spendkey_found)
+ {
cryptonote::blobdata spendkey_data;
- if(!epee::string_tools::parse_hexstr_to_binbuff(spendkey_string, spendkey_data))
+ if(!epee::string_tools::parse_hexstr_to_binbuff(field_spendkey, spendkey_data))
{
fail_msg_writer() << tr("failed to parse spend key secret key");
return false;
@@ -887,30 +883,32 @@ bool simple_wallet::generate_from_json(const boost::program_options::variables_m
spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
}
- std::string seed("");
+ GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, seed, std::string, String, false);
std::string old_language;
- if (json.HasMember("seed")) {
- seed = json["seed"].GetString();
- if (!crypto::ElectrumWords::words_to_bytes(seed, m_recovery_key, old_language))
+ if (field_seed_found)
+ {
+ if (!crypto::ElectrumWords::words_to_bytes(field_seed, m_recovery_key, old_language))
{
fail_msg_writer() << tr("Electrum-style word list failed verification");
return false;
}
- m_electrum_seed = seed;
+ m_electrum_seed = field_seed;
m_restore_deterministic_wallet = true;
}
// compatibility checks
- if (seed.empty() && viewkey_string.empty()) {
+ if (!field_seed_found && !field_viewkey_found)
+ {
fail_msg_writer() << tr("At least one of Electrum-style word list and private view key must be specified");
return false;
}
- if (!seed.empty() && (!viewkey_string.empty() || !spendkey_string.empty())) {
+ if (field_seed_found && (field_viewkey_found || field_spendkey_found))
+ {
fail_msg_writer() << tr("Both Electrum-style word list and private key(s) specified");
return false;
}
- m_wallet_file = filename;
+ m_wallet_file = field_filename;
bool was_deprecated_wallet = m_restore_deterministic_wallet && ((old_language == crypto::ElectrumWords::old_language_name) ||
crypto::ElectrumWords::get_is_old_style_seed(m_electrum_seed));
@@ -925,7 +923,7 @@ bool simple_wallet::generate_from_json(const boost::program_options::variables_m
try
{
- if (!seed.empty())
+ if (!field_seed.empty())
{
m_wallet->generate(m_wallet_file, password, m_recovery_key, recover, false);
}
@@ -941,7 +939,7 @@ bool simple_wallet::generate_from_json(const boost::program_options::variables_m
return false;
}
- if (spendkey_string.empty())
+ if (field_spendkey.empty())
{
m_wallet->generate(m_wallet_file, password, address, viewkey);
}
@@ -957,13 +955,44 @@ bool simple_wallet::generate_from_json(const boost::program_options::variables_m
return false;
}
- m_wallet->set_refresh_from_block_height(scan_from_height);
+ m_wallet->set_refresh_from_block_height(field_scan_from_height);
wallet_file = m_wallet_file;
return r;
}
+static bool is_local_daemon(const std::string &address)
+{
+ // extract host
+ epee::net_utils::http::url_content u_c;
+ if (!epee::net_utils::parse_url(address, u_c))
+ {
+ LOG_PRINT_L1("Failed to determine whether daemon is local, assuming not");
+ return false;
+ }
+ if (u_c.host.empty())
+ {
+ LOG_PRINT_L1("Failed to determine whether daemon is local, assuming not");
+ return false;
+ }
+
+ // resolve to IP
+ boost::asio::io_service io_service;
+ boost::asio::ip::tcp::resolver resolver(io_service);
+ boost::asio::ip::tcp::resolver::query query(u_c.host, "");
+ boost::asio::ip::tcp::resolver::iterator i = resolver.resolve(query);
+ while (i != boost::asio::ip::tcp::resolver::iterator())
+ {
+ const boost::asio::ip::tcp::endpoint &ep = *i;
+ if (ep.address().is_loopback())
+ return true;
+ ++i;
+ }
+
+ return false;
+}
+
//----------------------------------------------------------------------------------------------------
bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
@@ -999,6 +1028,17 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
if (m_daemon_address.empty())
m_daemon_address = std::string("http://") + m_daemon_host + ":" + std::to_string(m_daemon_port);
+ // set --trusted-daemon if local
+ try
+ {
+ if (is_local_daemon(m_daemon_address))
+ {
+ LOG_PRINT_L1(tr("Daemon is local, assuming trusted"));
+ m_trusted_daemon = true;
+ }
+ }
+ catch (const std::exception &e) { }
+
tools::password_container pwd_container;
if (!get_password(vm, true, pwd_container))
return false;
@@ -1020,6 +1060,8 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
if (m_electrum_seed.empty())
{
m_electrum_seed = command_line::input_line("Specify Electrum seed: ");
+ if (std::cin.eof())
+ return false;
if (m_electrum_seed.empty())
{
fail_msg_writer() << tr("specify a recovery parameter with the --electrum-seed=\"words list here\"");
@@ -1037,6 +1079,8 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
// parse address
std::string address_string = command_line::input_line("Standard address: ");
+ if (std::cin.eof())
+ return false;
if (address_string.empty()) {
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
@@ -1052,6 +1096,8 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
// parse view secret key
std::string viewkey_string = command_line::input_line("View key: ");
+ if (std::cin.eof())
+ return false;
if (viewkey_string.empty()) {
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
@@ -1084,6 +1130,8 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
// parse address
std::string address_string = command_line::input_line("Standard address: ");
+ if (std::cin.eof())
+ return false;
if (address_string.empty()) {
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
@@ -1099,6 +1147,8 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
// parse spend secret key
std::string spendkey_string = command_line::input_line("Spend key: ");
+ if (std::cin.eof())
+ return false;
if (spendkey_string.empty()) {
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
@@ -1113,6 +1163,8 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
// parse view secret key
std::string viewkey_string = command_line::input_line("View key: ");
+ if (std::cin.eof())
+ return false;
if (viewkey_string.empty()) {
fail_msg_writer() << tr("No data supplied, cancelled");
return false;
@@ -1232,6 +1284,8 @@ std::string simple_wallet::get_mnemonic_language()
while (language_number < 0)
{
language_choice = command_line::input_line(tr("Enter the number corresponding to the language of your choice: "));
+ if (std::cin.eof())
+ return std::string();
try
{
language_number = std::stoi(language_choice);
@@ -1270,6 +1324,8 @@ bool simple_wallet::new_wallet(const std::string &wallet_file, const std::string
"a deprecated version of the wallet. Please use the new seed that we provide.\n");
}
mnemonic_language = get_mnemonic_language();
+ if (mnemonic_language.empty())
+ return false;
}
m_wallet_file = wallet_file;
@@ -1397,6 +1453,8 @@ bool simple_wallet::open_wallet(const string &wallet_file, const std::string& pa
message_writer(epee::log_space::console_color_green, false) << "\n" << tr("You had been using "
"a deprecated version of the wallet. Please proceed to upgrade your wallet.\n");
std::string mnemonic_language = get_mnemonic_language();
+ if (mnemonic_language.empty())
+ return false;
m_wallet->set_seed_language(mnemonic_language);
m_wallet->rewrite(m_wallet_file, password);
@@ -2013,6 +2071,10 @@ bool simple_wallet::transfer_main(bool new_algorithm, const std::vector<std::str
// 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 true;
+ }
if (confirm_dns_ok != "Y" && confirm_dns_ok != "y" && confirm_dns_ok != "Yes" && confirm_dns_ok != "yes"
&& confirm_dns_ok != tr("yes") && confirm_dns_ok != tr("no"))
{
@@ -2097,6 +2159,8 @@ bool simple_wallet::transfer_main(bool new_algorithm, const std::vector<std::str
print_money(total_fee)).str();
}
std::string accepted = command_line::input_line(prompt_str);
+ if (std::cin.eof())
+ return true;
if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes")
{
fail_msg_writer() << tr("transaction cancelled.");
@@ -2159,6 +2223,9 @@ bool simple_wallet::transfer_main(bool new_algorithm, const std::vector<std::str
catch (const tools::error::tx_rejected& e)
{
fail_msg_writer() << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status();
+ std::string reason = e.reason();
+ if (!reason.empty())
+ fail_msg_writer() << tr("Reason: ") << reason;
}
catch (const tools::error::tx_sum_overflow& e)
{
@@ -2254,6 +2321,8 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
print_money(total_fee)).str();
}
std::string accepted = command_line::input_line(prompt_str);
+ if (std::cin.eof())
+ return true;
if (accepted != "Y" && accepted != "y" && accepted != "Yes" && accepted != "yes")
{
fail_msg_writer() << tr("transaction cancelled.");
@@ -2316,6 +2385,9 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
catch (const tools::error::tx_rejected& e)
{
fail_msg_writer() << (boost::format(tr("transaction %s was rejected by daemon with status: ")) % get_transaction_hash(e.tx())) << e.status();
+ std::string reason = e.reason();
+ if (!reason.empty())
+ fail_msg_writer() << tr("Reason: ") << reason;
}
catch (const tools::error::tx_sum_overflow& e)
{