aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRiccardo Spagni <ric@spagni.net>2017-11-14 21:31:50 +0200
committerRiccardo Spagni <ric@spagni.net>2017-11-14 21:31:51 +0200
commitedebe4e3b603fc391c698bf4d291336ba9376665 (patch)
tree53d687f5767f456284607ffa8e2808b251f2d7a0 /src
parentMerge pull request #2644 (diff)
parentDo not build against epee_readline if it was not built (diff)
downloadmonero-edebe4e3b603fc391c698bf4d291336ba9376665.tar.xz
Merge pull request #2736
0d9c0db9 Do not build against epee_readline if it was not built (Howard Chu) 178014c9 split off readline code into epee_readline (moneromooo-monero) a9e14a19 link against readline only for monerod and wallet-wallet-{rpc,cli} (moneromooo-monero) 437421ce wallet: move some scoped_message_writer calls from the libs (moneromooo-monero) e89994e9 wallet: rejig to avoid prompting in wallet2 (moneromooo-monero) ec5135e5 move input_line from command_line to simplewallet (moneromooo-monero) 082db75f move cryptonote command line options to cryptonote_core (moneromooo-monero)
Diffstat (limited to 'src')
-rw-r--r--src/blockchain_utilities/blockchain_export.cpp16
-rw-r--r--src/blockchain_utilities/blockchain_import.cpp9
-rw-r--r--src/common/command_line.cpp63
-rw-r--r--src/common/command_line.h15
-rw-r--r--src/common/password.cpp7
-rw-r--r--src/common/password.h2
-rw-r--r--src/cryptonote_core/cryptonote_core.cpp115
-rw-r--r--src/cryptonote_core/cryptonote_core.h5
-rw-r--r--src/daemon/CMakeLists.txt3
-rw-r--r--src/daemon/daemon.cpp2
-rw-r--r--src/daemon/main.cpp14
-rw-r--r--src/p2p/net_node.inl5
-rw-r--r--src/rpc/core_rpc_server.cpp2
-rw-r--r--src/rpc/rpc_args.cpp4
-rw-r--r--src/simplewallet/CMakeLists.txt3
-rw-r--r--src/simplewallet/simplewallet.cpp100
-rw-r--r--src/wallet/CMakeLists.txt1
-rw-r--r--src/wallet/wallet2.cpp155
-rw-r--r--src/wallet/wallet2.h11
-rw-r--r--src/wallet/wallet_args.cpp33
-rw-r--r--src/wallet/wallet_args.h1
-rw-r--r--src/wallet/wallet_errors.h6
-rw-r--r--src/wallet/wallet_rpc_server.cpp30
23 files changed, 312 insertions, 290 deletions
diff --git a/src/blockchain_utilities/blockchain_export.cpp b/src/blockchain_utilities/blockchain_export.cpp
index 60672eeda..78bb51ab6 100644
--- a/src/blockchain_utilities/blockchain_export.cpp
+++ b/src/blockchain_utilities/blockchain_export.cpp
@@ -30,6 +30,7 @@
#include "blocksdat_file.h"
#include "common/command_line.h"
#include "cryptonote_core/tx_pool.h"
+#include "cryptonote_core/cryptonote_core.h"
#include "blockchain_db/blockchain_db.h"
#include "blockchain_db/db_types.h"
#include "version.h"
@@ -66,21 +67,16 @@ int main(int argc, char* argv[])
const command_line::arg_descriptor<std::string> arg_output_file = {"output-file", "Specify output file", "", true};
const command_line::arg_descriptor<std::string> arg_log_level = {"log-level", "0-4 or categories", ""};
const command_line::arg_descriptor<uint64_t> arg_block_stop = {"block-stop", "Stop at block number", block_stop};
- const command_line::arg_descriptor<bool> arg_testnet_on = {
- "testnet"
- , "Run on testnet."
- , false
- };
const command_line::arg_descriptor<std::string> arg_database = {
"database", available_dbs.c_str(), default_db_type
};
const command_line::arg_descriptor<bool> arg_blocks_dat = {"blocksdat", "Output in blocks.dat format", blocks_dat};
- command_line::add_arg(desc_cmd_sett, command_line::arg_data_dir, default_data_path.string());
- command_line::add_arg(desc_cmd_sett, command_line::arg_testnet_data_dir, default_testnet_data_path.string());
+ command_line::add_arg(desc_cmd_sett, cryptonote::arg_data_dir, default_data_path.string());
+ command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_data_dir, default_testnet_data_path.string());
command_line::add_arg(desc_cmd_sett, arg_output_file);
- command_line::add_arg(desc_cmd_sett, arg_testnet_on);
+ command_line::add_arg(desc_cmd_sett, cryptonote::arg_testnet_on);
command_line::add_arg(desc_cmd_sett, arg_log_level);
command_line::add_arg(desc_cmd_sett, arg_database);
command_line::add_arg(desc_cmd_sett, arg_block_stop);
@@ -117,12 +113,12 @@ int main(int argc, char* argv[])
LOG_PRINT_L0("Starting...");
- bool opt_testnet = command_line::get_arg(vm, arg_testnet_on);
+ bool opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
bool opt_blocks_dat = command_line::get_arg(vm, arg_blocks_dat);
std::string m_config_folder;
- auto data_dir_arg = opt_testnet ? command_line::arg_testnet_data_dir : command_line::arg_data_dir;
+ auto data_dir_arg = opt_testnet ? cryptonote::arg_testnet_data_dir : cryptonote::arg_data_dir;
m_config_folder = command_line::get_arg(vm, data_dir_arg);
std::string db_type = command_line::get_arg(vm, arg_database);
diff --git a/src/blockchain_utilities/blockchain_import.cpp b/src/blockchain_utilities/blockchain_import.cpp
index 2153383bb..a50b0bad6 100644
--- a/src/blockchain_utilities/blockchain_import.cpp
+++ b/src/blockchain_utilities/blockchain_import.cpp
@@ -585,11 +585,6 @@ int main(int argc, char* argv[])
const command_line::arg_descriptor<uint64_t> arg_batch_size = {"batch-size", "", db_batch_size};
const command_line::arg_descriptor<uint64_t> arg_pop_blocks = {"pop-blocks", "Remove blocks from end of blockchain", num_blocks};
const command_line::arg_descriptor<bool> arg_drop_hf = {"drop-hard-fork", "Drop hard fork subdbs", false};
- const command_line::arg_descriptor<bool> arg_testnet_on = {
- "testnet"
- , "Run on testnet."
- , false
- };
const command_line::arg_descriptor<bool> arg_count_blocks = {
"count-blocks"
, "Count blocks in bootstrap file and exit"
@@ -674,8 +669,8 @@ int main(int argc, char* argv[])
}
}
- opt_testnet = command_line::get_arg(vm, arg_testnet_on);
- auto data_dir_arg = opt_testnet ? command_line::arg_testnet_data_dir : command_line::arg_data_dir;
+ opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
+ auto data_dir_arg = opt_testnet ? cryptonote::arg_testnet_data_dir : cryptonote::arg_data_dir;
m_config_folder = command_line::get_arg(vm, data_dir_arg);
db_arg_str = command_line::get_arg(vm, arg_database);
diff --git a/src/common/command_line.cpp b/src/common/command_line.cpp
index d4a28fc85..4b9ca9559 100644
--- a/src/common/command_line.cpp
+++ b/src/common/command_line.cpp
@@ -36,10 +36,6 @@
#include "cryptonote_config.h"
#include "string_tools.h"
-#ifdef HAVE_READLINE
- #include "readline_buffer.h"
-#endif
-
namespace command_line
{
namespace
@@ -50,20 +46,6 @@ namespace command_line
}
}
- std::string input_line(const std::string& prompt)
- {
-#ifdef HAVE_READLINE
- rdln::suspend_readline pause_readline;
-#endif
- std::cout << prompt;
-
- std::string buf;
- std::getline(std::cin, buf);
-
- return epee::string_tools::trim(buf);
-
- }
-
bool is_yes(const std::string& str)
{
if (str == "y" || str == "Y")
@@ -94,49 +76,4 @@ namespace command_line
const arg_descriptor<bool> arg_help = {"help", "Produce help message"};
const arg_descriptor<bool> arg_version = {"version", "Output version information"};
- const arg_descriptor<std::string> arg_data_dir = {"data-dir", "Specify data directory"};
- const arg_descriptor<std::string> arg_testnet_data_dir = {"testnet-data-dir", "Specify testnet data directory"};
- const arg_descriptor<bool> arg_test_drop_download = {"test-drop-download", "For net tests: in download, discard ALL blocks instead checking/saving them (very fast)"};
- const arg_descriptor<uint64_t> arg_test_drop_download_height = {"test-drop-download-height", "Like test-drop-download but disards only after around certain height", 0};
- const arg_descriptor<int> arg_test_dbg_lock_sleep = {"test-dbg-lock-sleep", "Sleep time in ms, defaults to 0 (off), used to debug before/after locking mutex. Values 100 to 1000 are good for tests."};
- const arg_descriptor<bool, false> arg_testnet_on = {
- "testnet"
- , "Run on testnet. The wallet must be launched with --testnet flag."
- , false
- };
- const arg_descriptor<bool> arg_dns_checkpoints = {
- "enforce-dns-checkpointing"
- , "checkpoints from DNS server will be enforced"
- , false
- };
- const command_line::arg_descriptor<uint64_t> arg_fast_block_sync = {
- "fast-block-sync"
- , "Sync up most of the way by using embedded, known block hashes."
- , 1
- };
- const command_line::arg_descriptor<uint64_t> arg_prep_blocks_threads = {
- "prep-blocks-threads"
- , "Max number of threads to use when preparing block hashes in groups."
- , 4
- };
- const command_line::arg_descriptor<uint64_t> arg_show_time_stats = {
- "show-time-stats"
- , "Show time-stats when processing blocks/txs and disk synchronization."
- , 0
- };
- const command_line::arg_descriptor<size_t> arg_block_sync_size = {
- "block-sync-size"
- , "How many blocks to sync at once during chain synchronization (0 = adaptive)."
- , 0
- };
- const command_line::arg_descriptor<std::string> arg_check_updates = {
- "check-updates"
- , "Check for new versions of monero: [disabled|notify|download|update]"
- , "notify"
- };
- const arg_descriptor<bool> arg_fluffy_blocks = {
- "fluffy-blocks"
- , "Relay blocks as fluffy blocks where possible (automatic on testnet)"
- , false
- };
}
diff --git a/src/common/command_line.h b/src/common/command_line.h
index bfc8b19c6..c2bac9cc8 100644
--- a/src/common/command_line.h
+++ b/src/common/command_line.h
@@ -41,8 +41,6 @@
namespace command_line
{
- std::string input_line(const std::string& prompt);
-
//! \return True if `str` is `is_iequal("y" || "yes" || `tr("yes"))`.
bool is_yes(const std::string& str);
//! \return True if `str` is `is_iequal("n" || "no" || `tr("no"))`.
@@ -213,17 +211,4 @@ namespace command_line
extern const arg_descriptor<bool> arg_help;
extern const arg_descriptor<bool> arg_version;
- extern const arg_descriptor<std::string> arg_data_dir;
- extern const arg_descriptor<std::string> arg_testnet_data_dir;
- extern const arg_descriptor<bool> arg_test_drop_download;
- extern const arg_descriptor<uint64_t> arg_test_drop_download_height;
- extern const arg_descriptor<int> arg_test_dbg_lock_sleep;
- extern const arg_descriptor<bool, false> arg_testnet_on;
- extern const arg_descriptor<bool> arg_dns_checkpoints;
- extern const arg_descriptor<uint64_t> arg_fast_block_sync;
- extern const arg_descriptor<uint64_t> arg_prep_blocks_threads;
- extern const arg_descriptor<uint64_t> arg_show_time_stats;
- extern const arg_descriptor<size_t> arg_block_sync_size;
- extern const arg_descriptor<std::string> arg_check_updates;
- extern const arg_descriptor<bool> arg_fluffy_blocks;
}
diff --git a/src/common/password.cpp b/src/common/password.cpp
index b84d6fb2e..5d56464a5 100644
--- a/src/common/password.cpp
+++ b/src/common/password.cpp
@@ -238,9 +238,6 @@ namespace tools
boost::optional<password_container> password_container::prompt(const bool verify, const char *message)
{
-#ifdef HAVE_READLINE
- rdln::suspend_readline pause_readline;
-#endif
password_container pass1{};
password_container pass2{};
if (is_cin_tty() ? read_from_tty(verify, message, pass1.m_password, pass2.m_password) : read_from_file(pass1.m_password))
@@ -249,7 +246,7 @@ namespace tools
return boost::none;
}
- boost::optional<login> login::parse(std::string&& userpass, bool verify, const char* message)
+ boost::optional<login> login::parse(std::string&& userpass, bool verify, const std::function<boost::optional<password_container>(bool)> &prompt)
{
login out{};
password_container wipe{std::move(userpass)};
@@ -257,7 +254,7 @@ namespace tools
const auto loc = wipe.password().find(':');
if (loc == std::string::npos)
{
- auto result = tools::password_container::prompt(verify, message);
+ auto result = prompt(verify);
if (!result)
return boost::none;
diff --git a/src/common/password.h b/src/common/password.h
index 12f715df4..ba1c30a28 100644
--- a/src/common/password.h
+++ b/src/common/password.h
@@ -82,7 +82,7 @@ namespace tools
\return The username and password, or boost::none if
`password_container::prompt` fails.
*/
- static boost::optional<login> parse(std::string&& userpass, bool verify, const char* message = "Password");
+ static boost::optional<login> parse(std::string&& userpass, bool verify, const std::function<boost::optional<password_container>(bool)> &prompt);
login(const login&) = delete;
login(login&&) = default;
diff --git a/src/cryptonote_core/cryptonote_core.cpp b/src/cryptonote_core/cryptonote_core.cpp
index a10692dad..acc76a8d6 100644
--- a/src/cryptonote_core/cryptonote_core.cpp
+++ b/src/cryptonote_core/cryptonote_core.cpp
@@ -38,6 +38,7 @@ using namespace epee;
#include "common/updates.h"
#include "common/download.h"
#include "common/threadpool.h"
+#include "common/command_line.h"
#include "warnings.h"
#include "crypto/crypto.h"
#include "cryptonote_config.h"
@@ -61,6 +62,69 @@ DISABLE_VS_WARNINGS(4355)
namespace cryptonote
{
+ const command_line::arg_descriptor<std::string> arg_data_dir = {
+ "data-dir"
+ , "Specify data directory"
+ };
+ const command_line::arg_descriptor<std::string> arg_testnet_data_dir = {
+ "testnet-data-dir"
+ , "Specify testnet data directory"
+ };
+ const command_line::arg_descriptor<bool, false> arg_testnet_on = {
+ "testnet"
+ , "Run on testnet. The wallet must be launched with --testnet flag."
+ , false
+ };
+
+ static const command_line::arg_descriptor<bool> arg_test_drop_download = {
+ "test-drop-download"
+ , "For net tests: in download, discard ALL blocks instead checking/saving them (very fast)"
+ };
+ static const command_line::arg_descriptor<uint64_t> arg_test_drop_download_height = {
+ "test-drop-download-height"
+ , "Like test-drop-download but disards only after around certain height"
+ , 0
+ };
+ static const command_line::arg_descriptor<int> arg_test_dbg_lock_sleep = {
+ "test-dbg-lock-sleep"
+ , "Sleep time in ms, defaults to 0 (off), used to debug before/after locking mutex. Values 100 to 1000 are good for tests."
+ , 0
+ };
+ static const command_line::arg_descriptor<bool> arg_dns_checkpoints = {
+ "enforce-dns-checkpointing"
+ , "checkpoints from DNS server will be enforced"
+ , false
+ };
+ static const command_line::arg_descriptor<uint64_t> arg_fast_block_sync = {
+ "fast-block-sync"
+ , "Sync up most of the way by using embedded, known block hashes."
+ , 1
+ };
+ static const command_line::arg_descriptor<uint64_t> arg_prep_blocks_threads = {
+ "prep-blocks-threads"
+ , "Max number of threads to use when preparing block hashes in groups."
+ , 4
+ };
+ static const command_line::arg_descriptor<uint64_t> arg_show_time_stats = {
+ "show-time-stats"
+ , "Show time-stats when processing blocks/txs and disk synchronization."
+ , 0
+ };
+ static const command_line::arg_descriptor<size_t> arg_block_sync_size = {
+ "block-sync-size"
+ , "How many blocks to sync at once during chain synchronization (0 = adaptive)."
+ , 0
+ };
+ static const command_line::arg_descriptor<std::string> arg_check_updates = {
+ "check-updates"
+ , "Check for new versions of monero: [disabled|notify|download|update]"
+ , "notify"
+ };
+ static const command_line::arg_descriptor<bool> arg_fluffy_blocks = {
+ "fluffy-blocks"
+ , "Relay blocks as fluffy blocks where possible (automatic on testnet)"
+ , false
+ };
//-----------------------------------------------------------------------------------------------
core::core(i_cryptonote_protocol* pprotocol):
@@ -148,20 +212,21 @@ namespace cryptonote
//-----------------------------------------------------------------------------------
void core::init_options(boost::program_options::options_description& desc)
{
- command_line::add_arg(desc, command_line::arg_data_dir, tools::get_default_data_dir());
- command_line::add_arg(desc, command_line::arg_testnet_data_dir, (boost::filesystem::path(tools::get_default_data_dir()) / "testnet").string());
+ command_line::add_arg(desc, arg_data_dir, tools::get_default_data_dir());
+ command_line::add_arg(desc, arg_testnet_data_dir, (boost::filesystem::path(tools::get_default_data_dir()) / "testnet").string());
- command_line::add_arg(desc, command_line::arg_test_drop_download);
- command_line::add_arg(desc, command_line::arg_test_drop_download_height);
+ command_line::add_arg(desc, arg_test_drop_download);
+ command_line::add_arg(desc, arg_test_drop_download_height);
- command_line::add_arg(desc, command_line::arg_testnet_on);
- command_line::add_arg(desc, command_line::arg_dns_checkpoints);
- command_line::add_arg(desc, command_line::arg_prep_blocks_threads);
- command_line::add_arg(desc, command_line::arg_fast_block_sync);
- command_line::add_arg(desc, command_line::arg_show_time_stats);
- command_line::add_arg(desc, command_line::arg_block_sync_size);
- command_line::add_arg(desc, command_line::arg_check_updates);
- command_line::add_arg(desc, command_line::arg_fluffy_blocks);
+ command_line::add_arg(desc, arg_testnet_on);
+ command_line::add_arg(desc, arg_dns_checkpoints);
+ command_line::add_arg(desc, arg_prep_blocks_threads);
+ command_line::add_arg(desc, arg_fast_block_sync);
+ command_line::add_arg(desc, arg_show_time_stats);
+ command_line::add_arg(desc, arg_block_sync_size);
+ command_line::add_arg(desc, arg_check_updates);
+ command_line::add_arg(desc, arg_fluffy_blocks);
+ command_line::add_arg(desc, arg_test_dbg_lock_sleep);
// we now also need some of net_node's options (p2p bind arg, for separate data dir)
command_line::add_arg(desc, nodetool::arg_testnet_p2p_bind_port, false);
@@ -173,9 +238,9 @@ namespace cryptonote
//-----------------------------------------------------------------------------------------------
bool core::handle_command_line(const boost::program_options::variables_map& vm)
{
- m_testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
+ m_testnet = command_line::get_arg(vm, arg_testnet_on);
- auto data_dir_arg = m_testnet ? command_line::arg_testnet_data_dir : command_line::arg_data_dir;
+ auto data_dir_arg = m_testnet ? arg_testnet_data_dir : arg_data_dir;
m_config_folder = command_line::get_arg(vm, data_dir_arg);
auto data_dir = boost::filesystem::path(m_config_folder);
@@ -196,13 +261,15 @@ namespace cryptonote
}
- set_enforce_dns_checkpoints(command_line::get_arg(vm, command_line::arg_dns_checkpoints));
- test_drop_download_height(command_line::get_arg(vm, command_line::arg_test_drop_download_height));
- m_fluffy_blocks_enabled = m_testnet || get_arg(vm, command_line::arg_fluffy_blocks);
+ set_enforce_dns_checkpoints(command_line::get_arg(vm, arg_dns_checkpoints));
+ test_drop_download_height(command_line::get_arg(vm, arg_test_drop_download_height));
+ m_fluffy_blocks_enabled = m_testnet || get_arg(vm, arg_fluffy_blocks);
- if (command_line::get_arg(vm, command_line::arg_test_drop_download) == true)
+ if (command_line::get_arg(vm, arg_test_drop_download) == true)
test_drop_download();
+ epee::debug::g_test_dbg_lock_sleep() = command_line::get_arg(vm, arg_test_dbg_lock_sleep);
+
return true;
}
//-----------------------------------------------------------------------------------------------
@@ -268,7 +335,7 @@ namespace cryptonote
m_fakechain = test_options != NULL;
bool r = handle_command_line(vm);
- bool testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
+ bool testnet = command_line::get_arg(vm, arg_testnet_on);
auto p2p_bind_arg = testnet ? nodetool::arg_testnet_p2p_bind_port : nodetool::arg_p2p_bind_port;
std::string m_port = command_line::get_arg(vm, p2p_bind_arg);
std::string m_config_folder_mempool = m_config_folder;
@@ -281,9 +348,9 @@ namespace cryptonote
std::string db_type = command_line::get_arg(vm, cryptonote::arg_db_type);
std::string db_sync_mode = command_line::get_arg(vm, cryptonote::arg_db_sync_mode);
bool db_salvage = command_line::get_arg(vm, cryptonote::arg_db_salvage) != 0;
- bool fast_sync = command_line::get_arg(vm, command_line::arg_fast_block_sync) != 0;
- uint64_t blocks_threads = command_line::get_arg(vm, command_line::arg_prep_blocks_threads);
- std::string check_updates_string = command_line::get_arg(vm, command_line::arg_check_updates);
+ bool fast_sync = command_line::get_arg(vm, arg_fast_block_sync) != 0;
+ uint64_t blocks_threads = command_line::get_arg(vm, arg_prep_blocks_threads);
+ std::string check_updates_string = command_line::get_arg(vm, arg_check_updates);
boost::filesystem::path folder(m_config_folder);
if (m_fakechain)
@@ -409,11 +476,11 @@ namespace cryptonote
// transactions in the pool that do not conform to the current fork
m_mempool.validate(m_blockchain_storage.get_current_hard_fork_version());
- bool show_time_stats = command_line::get_arg(vm, command_line::arg_show_time_stats) != 0;
+ bool show_time_stats = command_line::get_arg(vm, arg_show_time_stats) != 0;
m_blockchain_storage.set_show_time_stats(show_time_stats);
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage");
- block_sync_size = command_line::get_arg(vm, command_line::arg_block_sync_size);
+ block_sync_size = command_line::get_arg(vm, arg_block_sync_size);
MGINFO("Loading checkpoints");
diff --git a/src/cryptonote_core/cryptonote_core.h b/src/cryptonote_core/cryptonote_core.h
index a3d47280a..dc014206d 100644
--- a/src/cryptonote_core/cryptonote_core.h
+++ b/src/cryptonote_core/cryptonote_core.h
@@ -41,6 +41,7 @@
#include "storages/portable_storage_template_helper.h"
#include "common/download.h"
#include "common/threadpool.h"
+#include "common/command_line.h"
#include "tx_pool.h"
#include "blockchain.h"
#include "cryptonote_basic/miner.h"
@@ -58,6 +59,10 @@ namespace cryptonote
const std::pair<uint8_t, uint64_t> *hard_forks;
};
+ extern const command_line::arg_descriptor<std::string> arg_data_dir;
+ extern const command_line::arg_descriptor<std::string> arg_testnet_data_dir;
+ extern const command_line::arg_descriptor<bool, false> arg_testnet_on;
+
/************************************************************************/
/* */
/************************************************************************/
diff --git a/src/daemon/CMakeLists.txt b/src/daemon/CMakeLists.txt
index d0fc1d846..2f9c2b2f9 100644
--- a/src/daemon/CMakeLists.txt
+++ b/src/daemon/CMakeLists.txt
@@ -94,6 +94,8 @@ target_link_libraries(daemon
daemonizer
serialization
daemon_rpc_server
+ epee
+ ${EPEE_READLINE}
version
${Boost_CHRONO_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
@@ -102,6 +104,7 @@ target_link_libraries(daemon
${Boost_SYSTEM_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
${ZMQ_LIB}
+ ${Readline_LIBRARY}
${EXTRA_LIBRARIES})
set_property(TARGET daemon
PROPERTY
diff --git a/src/daemon/daemon.cpp b/src/daemon/daemon.cpp
index faa620c54..cf7d5f8ab 100644
--- a/src/daemon/daemon.cpp
+++ b/src/daemon/daemon.cpp
@@ -88,7 +88,7 @@ t_daemon::t_daemon(
)
: mp_internals{new t_internals{vm}}
{
- bool testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
+ bool testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
if (testnet)
{
zmq_rpc_bind_port = command_line::get_arg(vm, daemon_args::arg_zmq_testnet_rpc_bind_port);
diff --git a/src/daemon/main.cpp b/src/daemon/main.cpp
index 5d548f410..ae83943b6 100644
--- a/src/daemon/main.cpp
+++ b/src/daemon/main.cpp
@@ -82,7 +82,6 @@ int main(int argc, char const * argv[])
command_line::add_arg(visible_options, daemon_args::arg_os_version);
bf::path default_conf = default_data_dir / std::string(CRYPTONOTE_NAME ".conf");
command_line::add_arg(visible_options, daemon_args::arg_config_file, default_conf.string());
- command_line::add_arg(visible_options, command_line::arg_test_dbg_lock_sleep);
// Settings
bf::path default_log = default_data_dir / std::string(CRYPTONOTE_NAME ".log");
@@ -144,8 +143,6 @@ int main(int argc, char const * argv[])
return 0;
}
- epee::debug::g_test_dbg_lock_sleep() = command_line::get_arg(vm, command_line::arg_test_dbg_lock_sleep);
-
std::string db_type = command_line::get_arg(vm, cryptonote::arg_db_type);
// verify that blockchaindb type is valid
@@ -156,9 +153,9 @@ int main(int argc, char const * argv[])
return 0;
}
- bool testnet_mode = command_line::get_arg(vm, command_line::arg_testnet_on);
+ bool testnet_mode = command_line::get_arg(vm, cryptonote::arg_testnet_on);
- auto data_dir_arg = testnet_mode ? command_line::arg_testnet_data_dir : command_line::arg_data_dir;
+ auto data_dir_arg = testnet_mode ? cryptonote::arg_testnet_data_dir : cryptonote::arg_data_dir;
// data_dir
// default: e.g. ~/.bitmonero/ or ~/.bitmonero/testnet
@@ -250,7 +247,12 @@ int main(int argc, char const * argv[])
if (command_line::has_arg(vm, arg.rpc_login))
{
login = tools::login::parse(
- command_line::get_arg(vm, arg.rpc_login), false, "Daemon client password"
+ command_line::get_arg(vm, arg.rpc_login), false, [](bool verify) {
+#ifdef HAVE_READLINE
+ rdln::suspend_readline pause_readline;
+#endif
+ return tools::password_container::prompt(verify, "Daemon client password");
+ }
);
if (!login)
{
diff --git a/src/p2p/net_node.inl b/src/p2p/net_node.inl
index ee3ff160a..f64b29c1f 100644
--- a/src/p2p/net_node.inl
+++ b/src/p2p/net_node.inl
@@ -48,6 +48,7 @@
#include "net/local_ip.h"
#include "crypto/crypto.h"
#include "storages/levin_abstract_invoke2.h"
+#include "cryptonote_core/cryptonote_core.h"
// We have to look for miniupnpc headers in different places, dependent on if its compiled or external
#ifdef UPNP_STATIC
@@ -434,7 +435,7 @@ namespace nodetool
bool node_server<t_payload_net_handler>::init(const boost::program_options::variables_map& vm)
{
std::set<std::string> full_addrs;
- m_testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
+ m_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
if (m_testnet)
{
@@ -535,7 +536,7 @@ namespace nodetool
bool res = handle_command_line(vm);
CHECK_AND_ASSERT_MES(res, false, "Failed to handle command line");
- auto config_arg = m_testnet ? command_line::arg_testnet_data_dir : command_line::arg_data_dir;
+ auto config_arg = m_testnet ? cryptonote::arg_testnet_data_dir : cryptonote::arg_data_dir;
m_config_folder = command_line::get_arg(vm, config_arg);
if ((!m_testnet && m_port != std::to_string(::config::P2P_DEFAULT_PORT))
diff --git a/src/rpc/core_rpc_server.cpp b/src/rpc/core_rpc_server.cpp
index ba30a11c2..595aaec0f 100644
--- a/src/rpc/core_rpc_server.cpp
+++ b/src/rpc/core_rpc_server.cpp
@@ -85,7 +85,7 @@ namespace cryptonote
const boost::program_options::variables_map& vm
)
{
- m_testnet = command_line::get_arg(vm, command_line::arg_testnet_on);
+ m_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
m_net_server.set_threads_prefix("RPC");
auto p2p_bind_arg = m_testnet ? arg_testnet_rpc_bind_port : arg_rpc_bind_port;
diff --git a/src/rpc/rpc_args.cpp b/src/rpc/rpc_args.cpp
index 93309bf3c..e03c5472d 100644
--- a/src/rpc/rpc_args.cpp
+++ b/src/rpc/rpc_args.cpp
@@ -83,7 +83,9 @@ namespace cryptonote
if (command_line::has_arg(vm, arg.rpc_login))
{
- config.login = tools::login::parse(command_line::get_arg(vm, arg.rpc_login), true, "RPC server password");
+ config.login = tools::login::parse(command_line::get_arg(vm, arg.rpc_login), true, [](bool verify) {
+ return tools::password_container::prompt(verify, "RPC server password");
+ });
if (!config.login)
return boost::none;
diff --git a/src/simplewallet/CMakeLists.txt b/src/simplewallet/CMakeLists.txt
index 4ecda12d0..3ff4466fc 100644
--- a/src/simplewallet/CMakeLists.txt
+++ b/src/simplewallet/CMakeLists.txt
@@ -48,11 +48,14 @@ target_link_libraries(simplewallet
cncrypto
common
mnemonics
+ epee
+ ${EPEE_READLINE}
version
${Boost_CHRONO_LIBRARY}
${Boost_PROGRAM_OPTIONS_LIBRARY}
${Boost_FILESYSTEM_LIBRARY}
${Boost_THREAD_LIBRARY}
+ ${Readline_LIBRARY}
${CMAKE_THREAD_LIBS_INIT}
${EXTRA_LIBRARIES})
set_property(TARGET simplewallet
diff --git a/src/simplewallet/simplewallet.cpp b/src/simplewallet/simplewallet.cpp
index d09067fe3..b274675d1 100644
--- a/src/simplewallet/simplewallet.cpp
+++ b/src/simplewallet/simplewallet.cpp
@@ -125,6 +125,37 @@ namespace
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
+ std::string input_line(const std::string& prompt)
+ {
+#ifdef HAVE_READLINE
+ rdln::suspend_readline pause_readline;
+#endif
+ std::cout << prompt;
+
+ std::string buf;
+ std::getline(std::cin, buf);
+
+ return epee::string_tools::trim(buf);
+ }
+
+ boost::optional<tools::password_container> password_prompter(const char *prompt, bool verify)
+ {
+#ifdef HAVE_READLINE
+ rdln::suspend_readline pause_readline;
+#endif
+ auto pwd_container = tools::password_container::prompt(verify, prompt);
+ if (!pwd_container)
+ {
+ tools::fail_msg_writer() << tr("failed to read wallet password");
+ }
+ return pwd_container;
+ }
+
+ boost::optional<tools::password_container> default_password_prompter(bool verify)
+ {
+ return password_prompter(verify ? tr("Enter new wallet password") : tr("Wallet password"), verify);
+ }
+
inline std::string interpret_rpc_response(bool ok, const std::string& status)
{
std::string err;
@@ -270,7 +301,7 @@ namespace
<< 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());
+ std::string confirm_dns_ok = input_line(prompt.str());
if (std::cin.eof())
{
return {};
@@ -448,7 +479,7 @@ bool simple_wallet::change_password(const std::vector<std::string> &args)
}
// prompts for a new password, pass true to verify the password
- const auto pwd_container = tools::wallet2::password_prompt(true);
+ const auto pwd_container = default_password_prompter(true);
try
{
@@ -1020,7 +1051,7 @@ bool simple_wallet::ask_wallet_create_if_needed()
do{
LOG_PRINT_L3("User asked to specify wallet file name.");
- wallet_path = command_line::input_line(
+ wallet_path = input_line(
tr(m_restoring ? "Specify a new wallet file name for your restored wallet (e.g., MyWallet).\n"
"Wallet file name (or Ctrl-C to quit): " :
"Specify wallet file name (e.g., MyWallet). If the wallet doesn't exist, it will be created.\n"
@@ -1071,7 +1102,7 @@ bool simple_wallet::ask_wallet_create_if_needed()
if (!m_restoring)
{
message_writer() << tr("No wallet found with that name. Confirm creation of new wallet named: ") << wallet_path;
- confirm_creation = command_line::input_line(tr("(Y/Yes/N/No): "));
+ confirm_creation = input_line(tr("(Y/Yes/N/No): "));
if(std::cin.eof())
{
LOG_ERROR("Unexpected std::cin.eof() - Exited simple_wallet::ask_wallet_create_if_needed()");
@@ -1155,7 +1186,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
do
{
const char *prompt = m_electrum_seed.empty() ? "Specify Electrum seed: " : "Electrum seed continued: ";
- std::string electrum_seed = command_line::input_line(prompt);
+ std::string electrum_seed = input_line(prompt);
if (std::cin.eof())
return false;
if (electrum_seed.empty())
@@ -1184,7 +1215,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
m_wallet_file = m_generate_from_view_key;
// parse address
- std::string address_string = command_line::input_line("Standard address: ");
+ std::string address_string = input_line("Standard address: ");
if (std::cin.eof())
return false;
if (address_string.empty()) {
@@ -1204,7 +1235,7 @@ 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: ");
+ std::string viewkey_string = input_line("View key: ");
if (std::cin.eof())
return false;
if (viewkey_string.empty()) {
@@ -1258,7 +1289,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
m_wallet_file = m_generate_from_keys;
// parse address
- std::string address_string = command_line::input_line("Standard address: ");
+ std::string address_string = input_line("Standard address: ");
if (std::cin.eof())
return false;
if (address_string.empty()) {
@@ -1278,7 +1309,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
}
// parse spend secret key
- std::string spendkey_string = command_line::input_line("Secret spend key: ");
+ std::string spendkey_string = input_line("Secret spend key: ");
if (std::cin.eof())
return false;
if (spendkey_string.empty()) {
@@ -1294,7 +1325,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
crypto::secret_key spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
// parse view secret key
- std::string viewkey_string = command_line::input_line("Secret view key: ");
+ std::string viewkey_string = input_line("Secret view key: ");
if (std::cin.eof())
return false;
if (viewkey_string.empty()) {
@@ -1341,7 +1372,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
unsigned int multisig_n;
// parse multisig type
- std::string multisig_type_string = command_line::input_line("Multisig type (input as M/N with M <= N and M > 1): ");
+ std::string multisig_type_string = input_line("Multisig type (input as M/N with M <= N and M > 1): ");
if (std::cin.eof())
return false;
if (multisig_type_string.empty())
@@ -1367,7 +1398,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
message_writer() << boost::format(tr("Generating master wallet from %u of %u multisig wallet keys")) % multisig_m % multisig_n;
// parse multisig address
- std::string address_string = command_line::input_line("Multisig wallet address: ");
+ std::string address_string = input_line("Multisig wallet address: ");
if (std::cin.eof())
return false;
if (address_string.empty()) {
@@ -1382,7 +1413,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
}
// parse secret view key
- std::string viewkey_string = command_line::input_line("Secret view key: ");
+ std::string viewkey_string = input_line("Secret view key: ");
if (std::cin.eof())
return false;
if (viewkey_string.empty())
@@ -1422,7 +1453,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
// get N secret spend keys from user
for(unsigned int i=0; i<multisig_n; ++i)
{
- spendkey_string = command_line::input_line(tr((boost::format(tr("Secret spend key (%u of %u):")) % (i+i) % multisig_m).str().c_str()));
+ spendkey_string = input_line(tr((boost::format(tr("Secret spend key (%u of %u):")) % (i+i) % multisig_m).str().c_str()));
if (std::cin.eof())
return false;
if (spendkey_string.empty())
@@ -1470,7 +1501,15 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
else if (!m_generate_from_json.empty())
{
m_wallet_file = m_generate_from_json;
- m_wallet = tools::wallet2::make_from_json(vm, m_wallet_file);
+ try
+ {
+ m_wallet = tools::wallet2::make_from_json(vm, m_wallet_file, password_prompter);
+ }
+ catch (const std::exception &e)
+ {
+ fail_msg_writer() << e.what();
+ return false;
+ }
if (!m_wallet)
return false;
}
@@ -1492,9 +1531,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
{
std::string heightstr;
if (!connected || version < MAKE_CORE_RPC_VERSION(1, 6))
- heightstr = command_line::input_line("Restore from specific blockchain height (optional, default 0): ");
+ heightstr = input_line("Restore from specific blockchain height (optional, default 0): ");
else
- heightstr = command_line::input_line("Restore from specific blockchain height (optional, default 0),\nor alternatively from specific date (YYYY-MM-DD): ");
+ heightstr = input_line("Restore from specific blockchain height (optional, default 0),\nor alternatively from specific date (YYYY-MM-DD): ");
if (std::cin.eof())
return false;
if (heightstr.empty())
@@ -1530,7 +1569,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
day = boost::lexical_cast<uint16_t>(heightstr.substr(8,2));
m_restore_height = m_wallet->get_blockchain_height_by_date(year, month, day);
success_msg_writer() << tr("Restore height is: ") << m_restore_height;
- std::string confirm = command_line::input_line(tr("Is this okay? (Y/Yes/N/No): "));
+ std::string confirm = input_line(tr("Is this okay? (Y/Yes/N/No): "));
if (std::cin.eof())
return false;
if(command_line::is_yes(confirm))
@@ -1661,7 +1700,7 @@ 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: "));
+ language_choice = input_line(tr("Enter the number corresponding to the language of your choice: "));
if (std::cin.eof())
return std::string();
try
@@ -1683,7 +1722,7 @@ std::string simple_wallet::get_mnemonic_language()
//----------------------------------------------------------------------------------------------------
boost::optional<tools::password_container> simple_wallet::get_and_verify_password() const
{
- auto pwd_container = tools::wallet2::password_prompt(m_wallet_file.empty());
+ auto pwd_container = default_password_prompter(m_wallet_file.empty());
if (!pwd_container)
return boost::none;
@@ -1698,7 +1737,7 @@ boost::optional<tools::password_container> simple_wallet::get_and_verify_passwor
bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
const crypto::secret_key& recovery_key, bool recover, bool two_random, const std::string &old_language)
{
- auto rc = tools::wallet2::make_new(vm);
+ auto rc = tools::wallet2::make_new(vm, password_prompter);
m_wallet = std::move(rc.first);
if (!m_wallet)
{
@@ -1779,7 +1818,7 @@ bool simple_wallet::new_wallet(const boost::program_options::variables_map& vm,
const cryptonote::account_public_address& address, const boost::optional<crypto::secret_key>& spendkey,
const crypto::secret_key& viewkey)
{
- auto rc = tools::wallet2::make_new(vm);
+ auto rc = tools::wallet2::make_new(vm, password_prompter);
m_wallet = std::move(rc.first);
if (!m_wallet)
{
@@ -1821,7 +1860,7 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm)
std::string password;
try
{
- auto rc = tools::wallet2::make_from_file(vm, m_wallet_file);
+ auto rc = tools::wallet2::make_from_file(vm, m_wallet_file, password_prompter);
m_wallet = std::move(rc.first);
password = std::move(rc.second).password();
if (!m_wallet)
@@ -2806,7 +2845,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
// prompt is there is no payment id and confirmation is required
if (!payment_id_seen && m_wallet->confirm_missing_payment_id())
{
- std::string accepted = command_line::input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): "));
+ std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): "));
if (std::cin.eof())
return true;
if (!command_line::is_yes(accepted))
@@ -2890,7 +2929,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
std::string prompt_str = prompt.str();
if (!prompt_str.empty())
{
- std::string accepted = command_line::input_line(prompt_str);
+ std::string accepted = input_line(prompt_str);
if (std::cin.eof())
return true;
if (!command_line::is_yes(accepted))
@@ -2961,7 +3000,7 @@ bool simple_wallet::transfer_main(int transfer_type, const std::vector<std::stri
}
prompt << ENDL << tr("Is this okay? (Y/Yes/N/No): ");
- std::string accepted = command_line::input_line(prompt.str());
+ std::string accepted = input_line(prompt.str());
if (std::cin.eof())
return true;
if (!command_line::is_yes(accepted))
@@ -3058,7 +3097,7 @@ bool simple_wallet::sweep_unmixable(const std::vector<std::string> &args_)
print_money(total_unmixable) %
print_money(total_fee)).str();
}
- std::string accepted = command_line::input_line(prompt_str);
+ std::string accepted = input_line(prompt_str);
if (std::cin.eof())
return true;
if (!command_line::is_yes(accepted))
@@ -3219,7 +3258,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a
// prompt is there is no payment id and confirmation is required
if (!payment_id_seen && m_wallet->confirm_missing_payment_id())
{
- std::string accepted = command_line::input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): "));
+ std::string accepted = input_line(tr("No payment id is included with this transaction. Is this okay? (Y/Yes/N/No): "));
if (std::cin.eof())
return true;
if (!command_line::is_yes(accepted))
@@ -3277,7 +3316,7 @@ bool simple_wallet::sweep_main(uint64_t below, const std::vector<std::string> &a
print_money(total_sent) %
print_money(total_fee);
}
- std::string accepted = command_line::input_line(prompt.str());
+ std::string accepted = input_line(prompt.str());
if (std::cin.eof())
return true;
if (!command_line::is_yes(accepted))
@@ -3490,7 +3529,7 @@ bool simple_wallet::accept_loaded_tx(const std::function<size_t()> get_num_txes,
uint64_t fee = amount - amount_to_dests;
std::string prompt_str = (boost::format(tr("Loaded %lu transactions, for %s, fee %s, %s, %s, with min ring size %lu, %s. %sIs this okay? (Y/Yes/N/No): ")) % (unsigned long)get_num_txes() % print_money(amount) % print_money(fee) % dest_string % change_string % (unsigned long)min_ring_size % payment_id_string % extra_message).str();
- return command_line::is_yes(command_line::input_line(prompt_str));
+ return command_line::is_yes(input_line(prompt_str));
}
//----------------------------------------------------------------------------------------------------
bool simple_wallet::accept_loaded_tx(const tools::wallet2::unsigned_tx_set &txs)
@@ -5434,6 +5473,7 @@ int main(int argc, char* argv[])
"monero-wallet-cli [--wallet-file=<file>|--generate-new-wallet=<file>] [<COMMAND>]",
desc_params,
positional_options,
+ [](const std::string &s, bool emphasis){ tools::scoped_message_writer(emphasis ? epee::console_color_white : epee::console_color_default, true) << s; },
"monero-wallet-cli.log"
);
diff --git a/src/wallet/CMakeLists.txt b/src/wallet/CMakeLists.txt
index 4c00a4d51..7e061f480 100644
--- a/src/wallet/CMakeLists.txt
+++ b/src/wallet/CMakeLists.txt
@@ -108,6 +108,7 @@ if (NOT BUILD_GUI_DEPS)
PRIVATE
wallet
epee
+ ${EPEE_READLINE}
rpc
cryptonote_core
cncrypto
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp
index 50d07536c..9ed8e7cc3 100644
--- a/src/wallet/wallet2.cpp
+++ b/src/wallet/wallet2.cpp
@@ -137,7 +137,7 @@ uint64_t calculate_fee(uint64_t fee_per_kb, const cryptonote::blobdata &blob, ui
return calculate_fee(fee_per_kb, blob.size(), fee_multiplier);
}
-std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variables_map& vm, const options& opts)
+std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variables_map& vm, const options& opts, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
{
const bool testnet = command_line::get_arg(vm, opts.testnet);
const bool restricted = command_line::get_arg(vm, opts.restricted);
@@ -146,17 +146,16 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
auto daemon_host = command_line::get_arg(vm, opts.daemon_host);
auto daemon_port = command_line::get_arg(vm, opts.daemon_port);
- if (!daemon_address.empty() && !daemon_host.empty() && 0 != daemon_port)
- {
- tools::fail_msg_writer() << tools::wallet2::tr("can't specify daemon host or port more than once");
- return nullptr;
- }
+ THROW_WALLET_EXCEPTION_IF(!daemon_address.empty() && !daemon_host.empty() && 0 != daemon_port,
+ tools::error::wallet_internal_error, tools::wallet2::tr("can't specify daemon host or port more than once"));
boost::optional<epee::net_utils::http::login> login{};
if (command_line::has_arg(vm, opts.daemon_login))
{
auto parsed = tools::login::parse(
- command_line::get_arg(vm, opts.daemon_login), false, "Daemon client password"
+ command_line::get_arg(vm, opts.daemon_login), false, [password_prompter](bool verify) {
+ return password_prompter("Daemon client password", verify);
+ }
);
if (!parsed)
return nullptr;
@@ -180,12 +179,11 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
return wallet;
}
-boost::optional<tools::password_container> get_password(const boost::program_options::variables_map& vm, const options& opts, const bool verify)
+boost::optional<tools::password_container> get_password(const boost::program_options::variables_map& vm, const options& opts, const std::function<boost::optional<tools::password_container>(const char*, bool)> &password_prompter, const bool verify)
{
if (command_line::has_arg(vm, opts.password) && command_line::has_arg(vm, opts.password_file))
{
- tools::fail_msg_writer() << tools::wallet2::tr("can't specify more than one of --password and --password-file");
- return boost::none;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("can't specify more than one of --password and --password-file"));
}
if (command_line::has_arg(vm, opts.password))
@@ -198,21 +196,17 @@ boost::optional<tools::password_container> get_password(const boost::program_opt
std::string password;
bool r = epee::file_io_utils::load_file_to_string(command_line::get_arg(vm, opts.password_file),
password);
- if (!r)
- {
- tools::fail_msg_writer() << tools::wallet2::tr("the password file specified could not be read");
- return boost::none;
- }
+ THROW_WALLET_EXCEPTION_IF(!r, tools::error::wallet_internal_error, tools::wallet2::tr("the password file specified could not be read"));
// Remove line breaks the user might have inserted
boost::trim_right_if(password, boost::is_any_of("\r\n"));
return {tools::password_container{std::move(password)}};
}
- return tools::wallet2::password_prompt(verify);
+ return password_prompter(verify ? tr("Enter new wallet password") : tr("Wallet password"), verify);
}
-std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file, const boost::program_options::variables_map& vm, const options& opts)
+std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file, const boost::program_options::variables_map& vm, const options& opts, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
{
const bool testnet = command_line::get_arg(vm, opts.testnet);
@@ -223,22 +217,20 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
const auto do_generate = [&]() -> bool {
std::string buf;
if (!epee::file_io_utils::load_file_to_string(json_file, buf)) {
- tools::fail_msg_writer() << tools::wallet2::tr("Failed to load file ") << json_file;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, std::string(tools::wallet2::tr("Failed to load file ")) + json_file);
return false;
}
rapidjson::Document json;
if (json.Parse(buf.c_str()).HasParseError()) {
- tools::fail_msg_writer() << tools::wallet2::tr("Failed to parse JSON");
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("Failed to parse JSON"));
return false;
}
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, version, unsigned, Uint, true, 0);
const int current_version = 1;
- if (field_version > current_version) {
- tools::fail_msg_writer() << boost::format(tools::wallet2::tr("Version %u too new, we can only grok up to %u")) % field_version % current_version;
- return false;
- }
+ THROW_WALLET_EXCEPTION_IF(field_version > current_version, tools::error::wallet_internal_error,
+ ((boost::format(tools::wallet2::tr("Version %u too new, we can only grok up to %u")) % field_version % current_version)).str());
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, filename, std::string, String, true, std::string());
@@ -254,14 +246,12 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
cryptonote::blobdata viewkey_data;
if(!epee::string_tools::parse_hexstr_to_binbuff(field_viewkey, viewkey_data) || viewkey_data.size() != sizeof(crypto::secret_key))
{
- tools::fail_msg_writer() << tools::wallet2::tr("failed to parse view key secret key");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to parse view key secret key"));
}
viewkey = *reinterpret_cast<const crypto::secret_key*>(viewkey_data.data());
crypto::public_key pkey;
if (!crypto::secret_key_to_public_key(viewkey, pkey)) {
- tools::fail_msg_writer() << tools::wallet2::tr("failed to verify view key secret key");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify view key secret key"));
}
}
@@ -272,14 +262,12 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
cryptonote::blobdata spendkey_data;
if(!epee::string_tools::parse_hexstr_to_binbuff(field_spendkey, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key))
{
- tools::fail_msg_writer() << tools::wallet2::tr("failed to parse spend key secret key");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to parse spend key secret key"));
}
spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
crypto::public_key pkey;
if (!crypto::secret_key_to_public_key(spendkey, pkey)) {
- tools::fail_msg_writer() << tools::wallet2::tr("failed to verify spend key secret key");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify spend key secret key"));
}
}
@@ -291,8 +279,7 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
{
if (!crypto::ElectrumWords::words_to_bytes(field_seed, recovery_key, old_language))
{
- tools::fail_msg_writer() << tools::wallet2::tr("Electrum-style word list failed verification");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("Electrum-style word list failed verification"));
}
restore_deterministic_wallet = true;
@@ -309,13 +296,11 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
// compatibility checks
if (!field_seed_found && !field_viewkey_found && !field_spendkey_found)
{
- tools::fail_msg_writer() << tools::wallet2::tr("At least one of Electrum-style word list and private view key and private spend key must be specified");
- return false;
+ THROW_WALLET_EXCEPTION(tools::wallet2::tr("At least one of Electrum-style word list and private view key and private spend key must be specified"));
}
if (field_seed_found && (field_viewkey_found || field_spendkey_found))
{
- tools::fail_msg_writer() << tools::wallet2::tr("Both Electrum-style word list and private key(s) specified");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("Both Electrum-style word list and private key(s) specified"));
}
// if an address was given, we check keys against it, and deduce the spend
@@ -325,43 +310,36 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
cryptonote::address_parse_info info;
if(!get_account_address_from_str(info, testnet, field_address))
{
- tools::fail_msg_writer() << tools::wallet2::tr("invalid address");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("invalid address"));
}
if (field_viewkey_found)
{
crypto::public_key pkey;
if (!crypto::secret_key_to_public_key(viewkey, pkey)) {
- tools::fail_msg_writer() << tools::wallet2::tr("failed to verify view key secret key");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify view key secret key"));
}
if (info.address.m_view_public_key != pkey) {
- tools::fail_msg_writer() << tools::wallet2::tr("view key does not match standard address");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("view key does not match standard address"));
}
}
if (field_spendkey_found)
{
crypto::public_key pkey;
if (!crypto::secret_key_to_public_key(spendkey, pkey)) {
- tools::fail_msg_writer() << tools::wallet2::tr("failed to verify spend key secret key");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify spend key secret key"));
}
if (info.address.m_spend_public_key != pkey) {
- tools::fail_msg_writer() << tools::wallet2::tr("spend key does not match standard address");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("spend key does not match standard address"));
}
}
}
const bool deprecated_wallet = restore_deterministic_wallet && ((old_language == crypto::ElectrumWords::old_language_name) ||
crypto::ElectrumWords::get_is_old_style_seed(field_seed));
- if (deprecated_wallet) {
- tools::fail_msg_writer() << tools::wallet2::tr("Cannot create deprecated wallets from JSON");
- return false;
- }
+ THROW_WALLET_EXCEPTION_IF(deprecated_wallet, tools::error::wallet_internal_error,
+ tools::wallet2::tr("Cannot create deprecated wallets from JSON"));
- wallet.reset(make_basic(vm, opts).release());
+ wallet.reset(make_basic(vm, opts, password_prompter).release());
wallet->set_refresh_from_block_height(field_scan_from_height);
try
@@ -378,8 +356,7 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
{
cryptonote::account_public_address address;
if (!crypto::secret_key_to_public_key(viewkey, address.m_view_public_key)) {
- tools::fail_msg_writer() << tools::wallet2::tr("failed to verify view key secret key");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify view key secret key"));
}
if (field_spendkey.empty())
@@ -391,8 +368,7 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
cryptonote::address_parse_info info;
if(!get_account_address_from_str(info, testnet, field_address))
{
- tools::fail_msg_writer() << tools::wallet2::tr("failed to parse address: ") << field_address;
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, std::string(tools::wallet2::tr("failed to parse address: ")) + field_address);
}
address.m_spend_public_key = info.address.m_spend_public_key;
}
@@ -406,8 +382,7 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
else
{
if (!crypto::secret_key_to_public_key(spendkey, address.m_spend_public_key)) {
- tools::fail_msg_writer() << tools::wallet2::tr("failed to verify spend key secret key");
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify spend key secret key"));
}
wallet->generate(field_filename, field_password, address, spendkey, viewkey);
}
@@ -415,8 +390,7 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
}
catch (const std::exception& e)
{
- tools::fail_msg_writer() << tools::wallet2::tr("failed to generate new wallet: ") << e.what();
- return false;
+ THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, std::string(tools::wallet2::tr("failed to generate new wallet: ")) + e.what());
}
return true;
};
@@ -498,34 +472,22 @@ void wallet2::init_options(boost::program_options::options_description& desc_par
command_line::add_arg(desc_params, opts.restricted);
}
-boost::optional<password_container> wallet2::password_prompt(const bool new_password)
-{
- auto pwd_container = tools::password_container::prompt(
- new_password, (new_password ? tr("Enter new wallet password") : tr("Wallet password"))
- );
- if (!pwd_container)
- {
- tools::fail_msg_writer() << tr("failed to read wallet password");
- }
- return pwd_container;
-}
-
-std::unique_ptr<wallet2> wallet2::make_from_json(const boost::program_options::variables_map& vm, const std::string& json_file)
+std::unique_ptr<wallet2> wallet2::make_from_json(const boost::program_options::variables_map& vm, const std::string& json_file, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
{
const options opts{};
- return generate_from_json(json_file, vm, opts);
+ return generate_from_json(json_file, vm, opts, password_prompter);
}
std::pair<std::unique_ptr<wallet2>, password_container> wallet2::make_from_file(
- const boost::program_options::variables_map& vm, const std::string& wallet_file)
+ const boost::program_options::variables_map& vm, const std::string& wallet_file, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
{
const options opts{};
- auto pwd = get_password(vm, opts, false);
+ auto pwd = get_password(vm, opts, password_prompter, false);
if (!pwd)
{
return {nullptr, password_container{}};
}
- auto wallet = make_basic(vm, opts);
+ auto wallet = make_basic(vm, opts, password_prompter);
if (wallet)
{
wallet->load(wallet_file, pwd->password());
@@ -533,21 +495,21 @@ std::pair<std::unique_ptr<wallet2>, password_container> wallet2::make_from_file(
return {std::move(wallet), std::move(*pwd)};
}
-std::pair<std::unique_ptr<wallet2>, password_container> wallet2::make_new(const boost::program_options::variables_map& vm)
+std::pair<std::unique_ptr<wallet2>, password_container> wallet2::make_new(const boost::program_options::variables_map& vm, const std::function<boost::optional<password_container>(const char *, bool)> &password_prompter)
{
const options opts{};
- auto pwd = get_password(vm, opts, true);
+ auto pwd = get_password(vm, opts, password_prompter, true);
if (!pwd)
{
return {nullptr, password_container{}};
}
- return {make_basic(vm, opts), std::move(*pwd)};
+ return {make_basic(vm, opts, password_prompter), std::move(*pwd)};
}
-std::unique_ptr<wallet2> wallet2::make_dummy(const boost::program_options::variables_map& vm)
+std::unique_ptr<wallet2> wallet2::make_dummy(const boost::program_options::variables_map& vm, const std::function<boost::optional<tools::password_container>(const char *, bool)> &password_prompter)
{
const options opts{};
- return make_basic(vm, opts);
+ return make_basic(vm, opts, password_prompter);
}
//----------------------------------------------------------------------------------------------------
@@ -6525,16 +6487,12 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent
std::string data;
bool r = epee::file_io_utils::load_file_to_string(filename, data);
- if (!r)
- {
- fail_msg_writer() << tr("failed to read file ") << filename;
- return 0;
- }
+ THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, std::string(tr("failed to read file ")) + filename);
+
const size_t magiclen = strlen(KEY_IMAGE_EXPORT_FILE_MAGIC);
if (data.size() < magiclen || memcmp(data.data(), KEY_IMAGE_EXPORT_FILE_MAGIC, magiclen))
{
- fail_msg_writer() << "Bad key image export file magic in " << filename;
- return 0;
+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Bad key image export file magic in ") + filename);
}
try
@@ -6543,31 +6501,22 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent
}
catch (const std::exception &e)
{
- fail_msg_writer() << "Failed to decrypt " << filename << ": " << e.what();
- return 0;
+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to decrypt ") + filename + ": " + e.what());
}
const size_t headerlen = 2 * sizeof(crypto::public_key);
- if (data.size() < headerlen)
- {
- fail_msg_writer() << "Bad data size from file " << filename;
- return 0;
- }
+ THROW_WALLET_EXCEPTION_IF(data.size() < headerlen, error::wallet_internal_error, std::string("Bad data size from file ") + filename);
const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[0];
const crypto::public_key &public_view_key = *(const crypto::public_key*)&data[sizeof(crypto::public_key)];
const cryptonote::account_public_address &keys = get_account().get_keys().m_account_address;
if (public_spend_key != keys.m_spend_public_key || public_view_key != keys.m_view_public_key)
{
- fail_msg_writer() << "Key images from " << filename << " are for a different account";
- return 0;
+ THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string( "Key images from ") + filename + " are for a different account");
}
const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature);
- if ((data.size() - headerlen) % record_size)
- {
- fail_msg_writer() << "Bad data size from file " << filename;
- return 0;
- }
+ THROW_WALLET_EXCEPTION_IF((data.size() - headerlen) % record_size,
+ error::wallet_internal_error, std::string("Bad data size from file ") + filename);
size_t nki = (data.size() - headerlen) / record_size;
std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h
index 8576227e8..b07295253 100644
--- a/src/wallet/wallet2.h
+++ b/src/wallet/wallet2.h
@@ -155,21 +155,18 @@ namespace tools
static bool has_testnet_option(const boost::program_options::variables_map& vm);
static void init_options(boost::program_options::options_description& desc_params);
- //! \return Password retrieved from prompt. Logs error on failure.
- static boost::optional<password_container> password_prompt(const bool new_password);
-
//! Uses stdin and stdout. Returns a wallet2 if no errors.
- static std::unique_ptr<wallet2> make_from_json(const boost::program_options::variables_map& vm, const std::string& json_file);
+ static std::unique_ptr<wallet2> make_from_json(const boost::program_options::variables_map& vm, const std::string& json_file, const std::function<boost::optional<password_container>(const char *, bool)> &password_prompter);
//! Uses stdin and stdout. Returns a wallet2 and password for `wallet_file` if no errors.
static std::pair<std::unique_ptr<wallet2>, password_container>
- make_from_file(const boost::program_options::variables_map& vm, const std::string& wallet_file);
+ make_from_file(const boost::program_options::variables_map& vm, const std::string& wallet_file, const std::function<boost::optional<password_container>(const char *, bool)> &password_prompter);
//! Uses stdin and stdout. Returns a wallet2 and password for wallet with no file if no errors.
- static std::pair<std::unique_ptr<wallet2>, password_container> make_new(const boost::program_options::variables_map& vm);
+ static std::pair<std::unique_ptr<wallet2>, password_container> make_new(const boost::program_options::variables_map& vm, const std::function<boost::optional<password_container>(const char *, bool)> &password_prompter);
//! Just parses variables.
- static std::unique_ptr<wallet2> make_dummy(const boost::program_options::variables_map& vm);
+ static std::unique_ptr<wallet2> make_dummy(const boost::program_options::variables_map& vm, const std::function<boost::optional<password_container>(const char *, bool)> &password_prompter);
static bool verify_password(const std::string& keys_file_name, const std::string& password, bool watch_only);
diff --git a/src/wallet/wallet_args.cpp b/src/wallet/wallet_args.cpp
index df01ec238..cc6bb1de2 100644
--- a/src/wallet/wallet_args.cpp
+++ b/src/wallet/wallet_args.cpp
@@ -30,7 +30,6 @@
#include <boost/filesystem/path.hpp>
#include <boost/format.hpp>
#include "common/i18n.h"
-#include "common/scoped_message_writer.h"
#include "common/util.h"
#include "misc_log_ex.h"
#include "string_tools.h"
@@ -50,6 +49,20 @@
#define DEFAULT_MAX_CONCURRENCY 0
#endif
+namespace
+{
+ class Print
+ {
+ public:
+ Print(const std::function<void(const std::string&, bool)> &p, bool em = false): print(p), emphasis(em) {}
+ ~Print() { print(ss.str(), emphasis); }
+ template<typename T> std::ostream &operator<<(const T &t) { ss << t; return ss; }
+ private:
+ const std::function<void(const std::string&, bool)> &print;
+ std::stringstream ss;
+ bool emphasis;
+ };
+}
namespace wallet_args
{
@@ -73,6 +86,7 @@ namespace wallet_args
const char* const usage,
boost::program_options::options_description desc_params,
const boost::program_options::positional_options_description& positional_options,
+ const std::function<void(const std::string&, bool)> &print,
const char *default_log_name,
bool log_to_console)
@@ -118,16 +132,16 @@ namespace wallet_args
if (command_line::get_arg(vm, command_line::arg_help))
{
- tools::msg_writer() << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
- tools::msg_writer() << wallet_args::tr("This is the command line monero wallet. It needs to connect to a monero\n"
+ Print(print) << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
+ Print(print) << wallet_args::tr("This is the command line monero wallet. It needs to connect to a monero\n"
"daemon to work correctly.") << ENDL;
- tools::msg_writer() << wallet_args::tr("Usage:") << ENDL << " " << usage;
- tools::msg_writer() << desc_all;
+ Print(print) << wallet_args::tr("Usage:") << ENDL << " " << usage;
+ Print(print) << desc_all;
return false;
}
else if (command_line::get_arg(vm, command_line::arg_version))
{
- tools::msg_writer() << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
+ Print(print) << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
return false;
}
@@ -142,7 +156,7 @@ namespace wallet_args
}
else
{
- tools::fail_msg_writer() << wallet_args::tr("Can't find config file ") << config;
+ MERROR(wallet_args::tr("Can't find config file ") << config);
return false;
}
}
@@ -167,14 +181,15 @@ namespace wallet_args
if(command_line::has_arg(vm, arg_max_concurrency))
tools::set_max_concurrency(command_line::get_arg(vm, arg_max_concurrency));
- tools::scoped_message_writer(epee::console_color_white, true) << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
+ Print(print) << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")";
if (!command_line::is_arg_defaulted(vm, arg_log_level))
MINFO("Setting log level = " << command_line::get_arg(vm, arg_log_level));
else
MINFO("Setting log levels = " << getenv("MONERO_LOGS"));
MINFO(wallet_args::tr("Logging to: ") << log_path);
- tools::scoped_message_writer(epee::console_color_white, true) << boost::format(wallet_args::tr("Logging to %s")) % log_path;
+
+ Print(print) << boost::format(wallet_args::tr("Logging to %s")) % log_path;
return {std::move(vm)};
}
diff --git a/src/wallet/wallet_args.h b/src/wallet/wallet_args.h
index cf23ffded..8974098ad 100644
--- a/src/wallet/wallet_args.h
+++ b/src/wallet/wallet_args.h
@@ -50,5 +50,6 @@ namespace wallet_args
const char* const usage,
boost::program_options::options_description desc_params,
const boost::program_options::positional_options_description& positional_options,
+ const std::function<void(const std::string&, bool)> &print,
const char *default_log_name, bool log_to_console = false);
}
diff --git a/src/wallet/wallet_errors.h b/src/wallet/wallet_errors.h
index 9d66f125e..41eb77451 100644
--- a/src/wallet/wallet_errors.h
+++ b/src/wallet/wallet_errors.h
@@ -765,6 +765,12 @@ namespace tools
#define STRINGIZE_DETAIL(x) #x
#define STRINGIZE(x) STRINGIZE_DETAIL(x)
+#define THROW_WALLET_EXCEPTION(err_type, ...) \
+ do { \
+ LOG_ERROR("THROW EXCEPTION: " << #err_type); \
+ tools::error::throw_wallet_ex<err_type>(std::string(__FILE__ ":" STRINGIZE(__LINE__)), ## __VA_ARGS__); \
+ } while(0)
+
#define THROW_WALLET_EXCEPTION_IF(cond, err_type, ...) \
if (cond) \
{ \
diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp
index fda8f244a..173cc7bbe 100644
--- a/src/wallet/wallet_rpc_server.cpp
+++ b/src/wallet/wallet_rpc_server.cpp
@@ -38,6 +38,7 @@ using namespace epee;
#include "wallet/wallet_args.h"
#include "common/command_line.h"
#include "common/i18n.h"
+#include "common/scoped_message_writer.h"
#include "cryptonote_basic/cryptonote_format_utils.h"
#include "cryptonote_basic/account.h"
#include "wallet_rpc_server_commands_defs.h"
@@ -60,6 +61,16 @@ namespace
const command_line::arg_descriptor<std::string> arg_wallet_dir = {"wallet-dir", "Directory for newly created wallets"};
constexpr const char default_rpc_username[] = "monero";
+
+ boost::optional<tools::password_container> password_prompter(const char *prompt, bool verify)
+ {
+ auto pwd_container = tools::password_container::prompt(verify, prompt);
+ if (!pwd_container)
+ {
+ MERROR("failed to read wallet password");
+ }
+ return pwd_container;
+ }
}
namespace tools
@@ -131,7 +142,7 @@ namespace tools
walvars = m_wallet;
else
{
- tmpwal = tools::wallet2::make_dummy(*m_vm);
+ tmpwal = tools::wallet2::make_dummy(*m_vm, password_prompter);
walvars = tmpwal.get();
}
boost::optional<epee::net_utils::http::login> http_login{};
@@ -1798,7 +1809,7 @@ namespace tools
command_line::add_arg(desc, arg_password);
po::store(po::parse_command_line(argc, argv, desc), vm2);
}
- std::unique_ptr<tools::wallet2> wal = tools::wallet2::make_new(vm2).first;
+ std::unique_ptr<tools::wallet2> wal = tools::wallet2::make_new(vm2, password_prompter).first;
if (!wal)
{
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
@@ -1872,7 +1883,7 @@ namespace tools
}
std::unique_ptr<tools::wallet2> wal = nullptr;
try {
- wal = tools::wallet2::make_from_file(vm2, wallet_file).first;
+ wal = tools::wallet2::make_from_file(vm2, wallet_file, password_prompter).first;
}
catch (const std::exception& e)
{
@@ -1971,6 +1982,7 @@ int main(int argc, char** argv) {
"monero-wallet-rpc [--wallet-file=<file>|--generate-from-json=<file>|--wallet-dir=<directory>] [--rpc-bind-port=<port>]",
desc_params,
po::positional_options_description(),
+ [](const std::string &s, bool emphasis){ tools::scoped_message_writer(emphasis ? epee::console_color_white : epee::console_color_default, true) << s; },
"monero-wallet-rpc.log",
true
);
@@ -2007,11 +2019,19 @@ int main(int argc, char** argv) {
LOG_PRINT_L0(tools::wallet_rpc_server::tr("Loading wallet..."));
if(!wallet_file.empty())
{
- wal = tools::wallet2::make_from_file(*vm, wallet_file).first;
+ wal = tools::wallet2::make_from_file(*vm, wallet_file, password_prompter).first;
}
else
{
- wal = tools::wallet2::make_from_json(*vm, from_json);
+ try
+ {
+ wal = tools::wallet2::make_from_json(*vm, from_json, password_prompter);
+ }
+ catch (const std::exception &e)
+ {
+ MERROR("Error creating wallet: " << e.what());
+ return 1;
+ }
}
if (!wal)
{