mirror of
https://github.com/monero-project/monero.git
synced 2024-10-01 11:49:47 -04:00
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)
This commit is contained in:
commit
edebe4e3b6
@ -694,8 +694,8 @@ if(USE_READLINE)
|
|||||||
if(READLINE_FOUND AND GNU_READLINE_FOUND)
|
if(READLINE_FOUND AND GNU_READLINE_FOUND)
|
||||||
add_definitions(-DHAVE_READLINE)
|
add_definitions(-DHAVE_READLINE)
|
||||||
include_directories(${Readline_INCLUDE_DIR})
|
include_directories(${Readline_INCLUDE_DIR})
|
||||||
list(APPEND EXTRA_LIBRARIES ${Readline_LIBRARY})
|
|
||||||
message(STATUS "Found readline library at: ${Readline_ROOT_DIR}")
|
message(STATUS "Found readline library at: ${Readline_ROOT_DIR}")
|
||||||
|
set(EPEE_READLINE epee_readline)
|
||||||
else()
|
else()
|
||||||
message(STATUS "Could not find GNU readline library so building without readline support")
|
message(STATUS "Could not find GNU readline library so building without readline support")
|
||||||
endif()
|
endif()
|
||||||
|
@ -26,10 +26,9 @@
|
|||||||
# STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
|
# 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.
|
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
add_library(epee STATIC hex.cpp http_auth.cpp mlog.cpp net_utils_base.cpp string_tools.cpp)
|
||||||
if (USE_READLINE AND GNU_READLINE_FOUND)
|
if (USE_READLINE AND GNU_READLINE_FOUND)
|
||||||
add_library(epee STATIC hex.cpp http_auth.cpp mlog.cpp net_utils_base.cpp string_tools.cpp readline_buffer.cpp)
|
add_library(epee_readline STATIC readline_buffer.cpp)
|
||||||
else()
|
|
||||||
add_library(epee STATIC hex.cpp http_auth.cpp mlog.cpp net_utils_base.cpp string_tools.cpp)
|
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# Build and install libepee if we're building for GUI
|
# Build and install libepee if we're building for GUI
|
||||||
@ -41,6 +40,10 @@ if (BUILD_GUI_DEPS)
|
|||||||
endif()
|
endif()
|
||||||
install(TARGETS epee
|
install(TARGETS epee
|
||||||
ARCHIVE DESTINATION ${lib_folder})
|
ARCHIVE DESTINATION ${lib_folder})
|
||||||
|
if (USE_READLINE AND GNU_READLINE_FOUND)
|
||||||
|
install(TARGETS epee_readline
|
||||||
|
ARCHIVE DESTINATION ${lib_folder})
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
target_link_libraries(epee
|
target_link_libraries(epee
|
||||||
@ -51,3 +54,11 @@ target_link_libraries(epee
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
${OPENSSL_LIBRARIES}
|
${OPENSSL_LIBRARIES}
|
||||||
${EXTRA_LIBRARIES})
|
${EXTRA_LIBRARIES})
|
||||||
|
|
||||||
|
if (USE_READLINE AND GNU_READLINE_FOUND)
|
||||||
|
target_link_libraries(epee_readline
|
||||||
|
PUBLIC
|
||||||
|
easylogging
|
||||||
|
PRIVATE
|
||||||
|
${Readline_LIBRARY})
|
||||||
|
endif()
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include "blocksdat_file.h"
|
#include "blocksdat_file.h"
|
||||||
#include "common/command_line.h"
|
#include "common/command_line.h"
|
||||||
#include "cryptonote_core/tx_pool.h"
|
#include "cryptonote_core/tx_pool.h"
|
||||||
|
#include "cryptonote_core/cryptonote_core.h"
|
||||||
#include "blockchain_db/blockchain_db.h"
|
#include "blockchain_db/blockchain_db.h"
|
||||||
#include "blockchain_db/db_types.h"
|
#include "blockchain_db/db_types.h"
|
||||||
#include "version.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_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<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<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 = {
|
const command_line::arg_descriptor<std::string> arg_database = {
|
||||||
"database", available_dbs.c_str(), default_db_type
|
"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};
|
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, cryptonote::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_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_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_log_level);
|
||||||
command_line::add_arg(desc_cmd_sett, arg_database);
|
command_line::add_arg(desc_cmd_sett, arg_database);
|
||||||
command_line::add_arg(desc_cmd_sett, arg_block_stop);
|
command_line::add_arg(desc_cmd_sett, arg_block_stop);
|
||||||
@ -117,12 +113,12 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
LOG_PRINT_L0("Starting...");
|
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);
|
bool opt_blocks_dat = command_line::get_arg(vm, arg_blocks_dat);
|
||||||
|
|
||||||
std::string m_config_folder;
|
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);
|
m_config_folder = command_line::get_arg(vm, data_dir_arg);
|
||||||
|
|
||||||
std::string db_type = command_line::get_arg(vm, arg_database);
|
std::string db_type = command_line::get_arg(vm, arg_database);
|
||||||
|
@ -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_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<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_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 = {
|
const command_line::arg_descriptor<bool> arg_count_blocks = {
|
||||||
"count-blocks"
|
"count-blocks"
|
||||||
, "Count blocks in bootstrap file and exit"
|
, "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);
|
opt_testnet = command_line::get_arg(vm, cryptonote::arg_testnet_on);
|
||||||
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);
|
m_config_folder = command_line::get_arg(vm, data_dir_arg);
|
||||||
db_arg_str = command_line::get_arg(vm, arg_database);
|
db_arg_str = command_line::get_arg(vm, arg_database);
|
||||||
|
|
||||||
|
@ -36,10 +36,6 @@
|
|||||||
#include "cryptonote_config.h"
|
#include "cryptonote_config.h"
|
||||||
#include "string_tools.h"
|
#include "string_tools.h"
|
||||||
|
|
||||||
#ifdef HAVE_READLINE
|
|
||||||
#include "readline_buffer.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace command_line
|
namespace command_line
|
||||||
{
|
{
|
||||||
namespace
|
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)
|
bool is_yes(const std::string& str)
|
||||||
{
|
{
|
||||||
if (str == "y" || str == "Y")
|
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_help = {"help", "Produce help message"};
|
||||||
const arg_descriptor<bool> arg_version = {"version", "Output version information"};
|
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
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,6 @@
|
|||||||
namespace command_line
|
namespace command_line
|
||||||
{
|
{
|
||||||
|
|
||||||
std::string input_line(const std::string& prompt);
|
|
||||||
|
|
||||||
//! \return True if `str` is `is_iequal("y" || "yes" || `tr("yes"))`.
|
//! \return True if `str` is `is_iequal("y" || "yes" || `tr("yes"))`.
|
||||||
bool is_yes(const std::string& str);
|
bool is_yes(const std::string& str);
|
||||||
//! \return True if `str` is `is_iequal("n" || "no" || `tr("no"))`.
|
//! \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_help;
|
||||||
extern const arg_descriptor<bool> arg_version;
|
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;
|
|
||||||
}
|
}
|
||||||
|
@ -238,9 +238,6 @@ namespace tools
|
|||||||
|
|
||||||
boost::optional<password_container> password_container::prompt(const bool verify, const char *message)
|
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 pass1{};
|
||||||
password_container pass2{};
|
password_container pass2{};
|
||||||
if (is_cin_tty() ? read_from_tty(verify, message, pass1.m_password, pass2.m_password) : read_from_file(pass1.m_password))
|
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;
|
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{};
|
login out{};
|
||||||
password_container wipe{std::move(userpass)};
|
password_container wipe{std::move(userpass)};
|
||||||
@ -257,7 +254,7 @@ namespace tools
|
|||||||
const auto loc = wipe.password().find(':');
|
const auto loc = wipe.password().find(':');
|
||||||
if (loc == std::string::npos)
|
if (loc == std::string::npos)
|
||||||
{
|
{
|
||||||
auto result = tools::password_container::prompt(verify, message);
|
auto result = prompt(verify);
|
||||||
if (!result)
|
if (!result)
|
||||||
return boost::none;
|
return boost::none;
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ namespace tools
|
|||||||
\return The username and password, or boost::none if
|
\return The username and password, or boost::none if
|
||||||
`password_container::prompt` fails.
|
`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(const login&) = delete;
|
||||||
login(login&&) = default;
|
login(login&&) = default;
|
||||||
|
@ -38,6 +38,7 @@ using namespace epee;
|
|||||||
#include "common/updates.h"
|
#include "common/updates.h"
|
||||||
#include "common/download.h"
|
#include "common/download.h"
|
||||||
#include "common/threadpool.h"
|
#include "common/threadpool.h"
|
||||||
|
#include "common/command_line.h"
|
||||||
#include "warnings.h"
|
#include "warnings.h"
|
||||||
#include "crypto/crypto.h"
|
#include "crypto/crypto.h"
|
||||||
#include "cryptonote_config.h"
|
#include "cryptonote_config.h"
|
||||||
@ -61,6 +62,69 @@ DISABLE_VS_WARNINGS(4355)
|
|||||||
|
|
||||||
namespace cryptonote
|
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):
|
core::core(i_cryptonote_protocol* pprotocol):
|
||||||
@ -148,20 +212,21 @@ namespace cryptonote
|
|||||||
//-----------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------
|
||||||
void core::init_options(boost::program_options::options_description& desc)
|
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, 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_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, 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_height);
|
||||||
|
|
||||||
command_line::add_arg(desc, command_line::arg_testnet_on);
|
command_line::add_arg(desc, arg_testnet_on);
|
||||||
command_line::add_arg(desc, command_line::arg_dns_checkpoints);
|
command_line::add_arg(desc, arg_dns_checkpoints);
|
||||||
command_line::add_arg(desc, command_line::arg_prep_blocks_threads);
|
command_line::add_arg(desc, arg_prep_blocks_threads);
|
||||||
command_line::add_arg(desc, command_line::arg_fast_block_sync);
|
command_line::add_arg(desc, arg_fast_block_sync);
|
||||||
command_line::add_arg(desc, command_line::arg_show_time_stats);
|
command_line::add_arg(desc, arg_show_time_stats);
|
||||||
command_line::add_arg(desc, command_line::arg_block_sync_size);
|
command_line::add_arg(desc, arg_block_sync_size);
|
||||||
command_line::add_arg(desc, command_line::arg_check_updates);
|
command_line::add_arg(desc, arg_check_updates);
|
||||||
command_line::add_arg(desc, command_line::arg_fluffy_blocks);
|
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)
|
// 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);
|
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)
|
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);
|
m_config_folder = command_line::get_arg(vm, data_dir_arg);
|
||||||
|
|
||||||
auto data_dir = boost::filesystem::path(m_config_folder);
|
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));
|
set_enforce_dns_checkpoints(command_line::get_arg(vm, arg_dns_checkpoints));
|
||||||
test_drop_download_height(command_line::get_arg(vm, command_line::arg_test_drop_download_height));
|
test_drop_download_height(command_line::get_arg(vm, arg_test_drop_download_height));
|
||||||
m_fluffy_blocks_enabled = m_testnet || get_arg(vm, command_line::arg_fluffy_blocks);
|
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();
|
test_drop_download();
|
||||||
|
|
||||||
|
epee::debug::g_test_dbg_lock_sleep() = command_line::get_arg(vm, arg_test_dbg_lock_sleep);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
//-----------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------
|
||||||
@ -268,7 +335,7 @@ namespace cryptonote
|
|||||||
|
|
||||||
m_fakechain = test_options != NULL;
|
m_fakechain = test_options != NULL;
|
||||||
bool r = handle_command_line(vm);
|
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;
|
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_port = command_line::get_arg(vm, p2p_bind_arg);
|
||||||
std::string m_config_folder_mempool = m_config_folder;
|
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_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);
|
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 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;
|
bool fast_sync = command_line::get_arg(vm, arg_fast_block_sync) != 0;
|
||||||
uint64_t blocks_threads = command_line::get_arg(vm, command_line::arg_prep_blocks_threads);
|
uint64_t blocks_threads = command_line::get_arg(vm, arg_prep_blocks_threads);
|
||||||
std::string check_updates_string = command_line::get_arg(vm, command_line::arg_check_updates);
|
std::string check_updates_string = command_line::get_arg(vm, arg_check_updates);
|
||||||
|
|
||||||
boost::filesystem::path folder(m_config_folder);
|
boost::filesystem::path folder(m_config_folder);
|
||||||
if (m_fakechain)
|
if (m_fakechain)
|
||||||
@ -409,11 +476,11 @@ namespace cryptonote
|
|||||||
// transactions in the pool that do not conform to the current fork
|
// transactions in the pool that do not conform to the current fork
|
||||||
m_mempool.validate(m_blockchain_storage.get_current_hard_fork_version());
|
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);
|
m_blockchain_storage.set_show_time_stats(show_time_stats);
|
||||||
CHECK_AND_ASSERT_MES(r, false, "Failed to initialize blockchain storage");
|
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");
|
MGINFO("Loading checkpoints");
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
#include "storages/portable_storage_template_helper.h"
|
#include "storages/portable_storage_template_helper.h"
|
||||||
#include "common/download.h"
|
#include "common/download.h"
|
||||||
#include "common/threadpool.h"
|
#include "common/threadpool.h"
|
||||||
|
#include "common/command_line.h"
|
||||||
#include "tx_pool.h"
|
#include "tx_pool.h"
|
||||||
#include "blockchain.h"
|
#include "blockchain.h"
|
||||||
#include "cryptonote_basic/miner.h"
|
#include "cryptonote_basic/miner.h"
|
||||||
@ -58,6 +59,10 @@ namespace cryptonote
|
|||||||
const std::pair<uint8_t, uint64_t> *hard_forks;
|
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;
|
||||||
|
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
/* */
|
/* */
|
||||||
/************************************************************************/
|
/************************************************************************/
|
||||||
|
@ -94,6 +94,8 @@ target_link_libraries(daemon
|
|||||||
daemonizer
|
daemonizer
|
||||||
serialization
|
serialization
|
||||||
daemon_rpc_server
|
daemon_rpc_server
|
||||||
|
epee
|
||||||
|
${EPEE_READLINE}
|
||||||
version
|
version
|
||||||
${Boost_CHRONO_LIBRARY}
|
${Boost_CHRONO_LIBRARY}
|
||||||
${Boost_FILESYSTEM_LIBRARY}
|
${Boost_FILESYSTEM_LIBRARY}
|
||||||
@ -102,6 +104,7 @@ target_link_libraries(daemon
|
|||||||
${Boost_SYSTEM_LIBRARY}
|
${Boost_SYSTEM_LIBRARY}
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
${ZMQ_LIB}
|
${ZMQ_LIB}
|
||||||
|
${Readline_LIBRARY}
|
||||||
${EXTRA_LIBRARIES})
|
${EXTRA_LIBRARIES})
|
||||||
set_property(TARGET daemon
|
set_property(TARGET daemon
|
||||||
PROPERTY
|
PROPERTY
|
||||||
|
@ -88,7 +88,7 @@ t_daemon::t_daemon(
|
|||||||
)
|
)
|
||||||
: mp_internals{new t_internals{vm}}
|
: 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)
|
if (testnet)
|
||||||
{
|
{
|
||||||
zmq_rpc_bind_port = command_line::get_arg(vm, daemon_args::arg_zmq_testnet_rpc_bind_port);
|
zmq_rpc_bind_port = command_line::get_arg(vm, daemon_args::arg_zmq_testnet_rpc_bind_port);
|
||||||
|
@ -82,7 +82,6 @@ int main(int argc, char const * argv[])
|
|||||||
command_line::add_arg(visible_options, daemon_args::arg_os_version);
|
command_line::add_arg(visible_options, daemon_args::arg_os_version);
|
||||||
bf::path default_conf = default_data_dir / std::string(CRYPTONOTE_NAME ".conf");
|
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, daemon_args::arg_config_file, default_conf.string());
|
||||||
command_line::add_arg(visible_options, command_line::arg_test_dbg_lock_sleep);
|
|
||||||
|
|
||||||
// Settings
|
// Settings
|
||||||
bf::path default_log = default_data_dir / std::string(CRYPTONOTE_NAME ".log");
|
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;
|
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);
|
std::string db_type = command_line::get_arg(vm, cryptonote::arg_db_type);
|
||||||
|
|
||||||
// verify that blockchaindb type is valid
|
// verify that blockchaindb type is valid
|
||||||
@ -156,9 +153,9 @@ int main(int argc, char const * argv[])
|
|||||||
return 0;
|
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
|
// data_dir
|
||||||
// default: e.g. ~/.bitmonero/ or ~/.bitmonero/testnet
|
// 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))
|
if (command_line::has_arg(vm, arg.rpc_login))
|
||||||
{
|
{
|
||||||
login = tools::login::parse(
|
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)
|
if (!login)
|
||||||
{
|
{
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include "net/local_ip.h"
|
#include "net/local_ip.h"
|
||||||
#include "crypto/crypto.h"
|
#include "crypto/crypto.h"
|
||||||
#include "storages/levin_abstract_invoke2.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
|
// We have to look for miniupnpc headers in different places, dependent on if its compiled or external
|
||||||
#ifdef UPNP_STATIC
|
#ifdef UPNP_STATIC
|
||||||
@ -434,7 +435,7 @@ namespace nodetool
|
|||||||
bool node_server<t_payload_net_handler>::init(const boost::program_options::variables_map& vm)
|
bool node_server<t_payload_net_handler>::init(const boost::program_options::variables_map& vm)
|
||||||
{
|
{
|
||||||
std::set<std::string> full_addrs;
|
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)
|
if (m_testnet)
|
||||||
{
|
{
|
||||||
@ -535,7 +536,7 @@ namespace nodetool
|
|||||||
bool res = handle_command_line(vm);
|
bool res = handle_command_line(vm);
|
||||||
CHECK_AND_ASSERT_MES(res, false, "Failed to handle command line");
|
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);
|
m_config_folder = command_line::get_arg(vm, config_arg);
|
||||||
|
|
||||||
if ((!m_testnet && m_port != std::to_string(::config::P2P_DEFAULT_PORT))
|
if ((!m_testnet && m_port != std::to_string(::config::P2P_DEFAULT_PORT))
|
||||||
|
@ -85,7 +85,7 @@ namespace cryptonote
|
|||||||
const boost::program_options::variables_map& vm
|
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");
|
m_net_server.set_threads_prefix("RPC");
|
||||||
|
|
||||||
auto p2p_bind_arg = m_testnet ? arg_testnet_rpc_bind_port : arg_rpc_bind_port;
|
auto p2p_bind_arg = m_testnet ? arg_testnet_rpc_bind_port : arg_rpc_bind_port;
|
||||||
|
@ -83,7 +83,9 @@ namespace cryptonote
|
|||||||
|
|
||||||
if (command_line::has_arg(vm, arg.rpc_login))
|
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)
|
if (!config.login)
|
||||||
return boost::none;
|
return boost::none;
|
||||||
|
|
||||||
|
@ -48,11 +48,14 @@ target_link_libraries(simplewallet
|
|||||||
cncrypto
|
cncrypto
|
||||||
common
|
common
|
||||||
mnemonics
|
mnemonics
|
||||||
|
epee
|
||||||
|
${EPEE_READLINE}
|
||||||
version
|
version
|
||||||
${Boost_CHRONO_LIBRARY}
|
${Boost_CHRONO_LIBRARY}
|
||||||
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
${Boost_PROGRAM_OPTIONS_LIBRARY}
|
||||||
${Boost_FILESYSTEM_LIBRARY}
|
${Boost_FILESYSTEM_LIBRARY}
|
||||||
${Boost_THREAD_LIBRARY}
|
${Boost_THREAD_LIBRARY}
|
||||||
|
${Readline_LIBRARY}
|
||||||
${CMAKE_THREAD_LIBS_INIT}
|
${CMAKE_THREAD_LIBS_INIT}
|
||||||
${EXTRA_LIBRARIES})
|
${EXTRA_LIBRARIES})
|
||||||
set_property(TARGET simplewallet
|
set_property(TARGET simplewallet
|
||||||
|
@ -125,6 +125,37 @@ namespace
|
|||||||
|
|
||||||
const command_line::arg_descriptor< std::vector<std::string> > arg_command = {"command", ""};
|
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)
|
inline std::string interpret_rpc_response(bool ok, const std::string& status)
|
||||||
{
|
{
|
||||||
std::string err;
|
std::string err;
|
||||||
@ -270,7 +301,7 @@ namespace
|
|||||||
<< tr("Is this OK? (Y/n) ")
|
<< tr("Is this OK? (Y/n) ")
|
||||||
;
|
;
|
||||||
// prompt the user for confirmation given the dns query and dnssec status
|
// 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())
|
if (std::cin.eof())
|
||||||
{
|
{
|
||||||
return {};
|
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
|
// 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
|
try
|
||||||
{
|
{
|
||||||
@ -1020,7 +1051,7 @@ bool simple_wallet::ask_wallet_create_if_needed()
|
|||||||
|
|
||||||
do{
|
do{
|
||||||
LOG_PRINT_L3("User asked to specify wallet file name.");
|
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"
|
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): " :
|
"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"
|
"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)
|
if (!m_restoring)
|
||||||
{
|
{
|
||||||
message_writer() << tr("No wallet found with that name. Confirm creation of new wallet named: ") << wallet_path;
|
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())
|
if(std::cin.eof())
|
||||||
{
|
{
|
||||||
LOG_ERROR("Unexpected std::cin.eof() - Exited simple_wallet::ask_wallet_create_if_needed()");
|
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
|
do
|
||||||
{
|
{
|
||||||
const char *prompt = m_electrum_seed.empty() ? "Specify Electrum seed: " : "Electrum seed continued: ";
|
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())
|
if (std::cin.eof())
|
||||||
return false;
|
return false;
|
||||||
if (electrum_seed.empty())
|
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;
|
m_wallet_file = m_generate_from_view_key;
|
||||||
// parse address
|
// parse address
|
||||||
std::string address_string = command_line::input_line("Standard address: ");
|
std::string address_string = input_line("Standard address: ");
|
||||||
if (std::cin.eof())
|
if (std::cin.eof())
|
||||||
return false;
|
return false;
|
||||||
if (address_string.empty()) {
|
if (address_string.empty()) {
|
||||||
@ -1204,7 +1235,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse view secret key
|
// 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())
|
if (std::cin.eof())
|
||||||
return false;
|
return false;
|
||||||
if (viewkey_string.empty()) {
|
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;
|
m_wallet_file = m_generate_from_keys;
|
||||||
// parse address
|
// parse address
|
||||||
std::string address_string = command_line::input_line("Standard address: ");
|
std::string address_string = input_line("Standard address: ");
|
||||||
if (std::cin.eof())
|
if (std::cin.eof())
|
||||||
return false;
|
return false;
|
||||||
if (address_string.empty()) {
|
if (address_string.empty()) {
|
||||||
@ -1278,7 +1309,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse spend secret key
|
// 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())
|
if (std::cin.eof())
|
||||||
return false;
|
return false;
|
||||||
if (spendkey_string.empty()) {
|
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());
|
crypto::secret_key spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
|
||||||
|
|
||||||
// parse view secret key
|
// 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())
|
if (std::cin.eof())
|
||||||
return false;
|
return false;
|
||||||
if (viewkey_string.empty()) {
|
if (viewkey_string.empty()) {
|
||||||
@ -1341,7 +1372,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||||||
unsigned int multisig_n;
|
unsigned int multisig_n;
|
||||||
|
|
||||||
// parse multisig type
|
// 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())
|
if (std::cin.eof())
|
||||||
return false;
|
return false;
|
||||||
if (multisig_type_string.empty())
|
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;
|
message_writer() << boost::format(tr("Generating master wallet from %u of %u multisig wallet keys")) % multisig_m % multisig_n;
|
||||||
|
|
||||||
// parse multisig address
|
// 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())
|
if (std::cin.eof())
|
||||||
return false;
|
return false;
|
||||||
if (address_string.empty()) {
|
if (address_string.empty()) {
|
||||||
@ -1382,7 +1413,7 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parse secret view key
|
// 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())
|
if (std::cin.eof())
|
||||||
return false;
|
return false;
|
||||||
if (viewkey_string.empty())
|
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
|
// get N secret spend keys from user
|
||||||
for(unsigned int i=0; i<multisig_n; ++i)
|
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())
|
if (std::cin.eof())
|
||||||
return false;
|
return false;
|
||||||
if (spendkey_string.empty())
|
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())
|
else if (!m_generate_from_json.empty())
|
||||||
{
|
{
|
||||||
m_wallet_file = m_generate_from_json;
|
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)
|
if (!m_wallet)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1492,9 +1531,9 @@ bool simple_wallet::init(const boost::program_options::variables_map& vm)
|
|||||||
{
|
{
|
||||||
std::string heightstr;
|
std::string heightstr;
|
||||||
if (!connected || version < MAKE_CORE_RPC_VERSION(1, 6))
|
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
|
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())
|
if (std::cin.eof())
|
||||||
return false;
|
return false;
|
||||||
if (heightstr.empty())
|
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));
|
day = boost::lexical_cast<uint16_t>(heightstr.substr(8,2));
|
||||||
m_restore_height = m_wallet->get_blockchain_height_by_date(year, month, day);
|
m_restore_height = m_wallet->get_blockchain_height_by_date(year, month, day);
|
||||||
success_msg_writer() << tr("Restore height is: ") << m_restore_height;
|
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())
|
if (std::cin.eof())
|
||||||
return false;
|
return false;
|
||||||
if(command_line::is_yes(confirm))
|
if(command_line::is_yes(confirm))
|
||||||
@ -1661,7 +1700,7 @@ std::string simple_wallet::get_mnemonic_language()
|
|||||||
}
|
}
|
||||||
while (language_number < 0)
|
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())
|
if (std::cin.eof())
|
||||||
return std::string();
|
return std::string();
|
||||||
try
|
try
|
||||||
@ -1683,7 +1722,7 @@ std::string simple_wallet::get_mnemonic_language()
|
|||||||
//----------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------
|
||||||
boost::optional<tools::password_container> simple_wallet::get_and_verify_password() const
|
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)
|
if (!pwd_container)
|
||||||
return boost::none;
|
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,
|
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)
|
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);
|
m_wallet = std::move(rc.first);
|
||||||
if (!m_wallet)
|
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 cryptonote::account_public_address& address, const boost::optional<crypto::secret_key>& spendkey,
|
||||||
const crypto::secret_key& viewkey)
|
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);
|
m_wallet = std::move(rc.first);
|
||||||
if (!m_wallet)
|
if (!m_wallet)
|
||||||
{
|
{
|
||||||
@ -1821,7 +1860,7 @@ bool simple_wallet::open_wallet(const boost::program_options::variables_map& vm)
|
|||||||
std::string password;
|
std::string password;
|
||||||
try
|
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);
|
m_wallet = std::move(rc.first);
|
||||||
password = std::move(rc.second).password();
|
password = std::move(rc.second).password();
|
||||||
if (!m_wallet)
|
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
|
// prompt is there is no payment id and confirmation is required
|
||||||
if (!payment_id_seen && m_wallet->confirm_missing_payment_id())
|
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())
|
if (std::cin.eof())
|
||||||
return true;
|
return true;
|
||||||
if (!command_line::is_yes(accepted))
|
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();
|
std::string prompt_str = prompt.str();
|
||||||
if (!prompt_str.empty())
|
if (!prompt_str.empty())
|
||||||
{
|
{
|
||||||
std::string accepted = command_line::input_line(prompt_str);
|
std::string accepted = input_line(prompt_str);
|
||||||
if (std::cin.eof())
|
if (std::cin.eof())
|
||||||
return true;
|
return true;
|
||||||
if (!command_line::is_yes(accepted))
|
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): ");
|
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())
|
if (std::cin.eof())
|
||||||
return true;
|
return true;
|
||||||
if (!command_line::is_yes(accepted))
|
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_unmixable) %
|
||||||
print_money(total_fee)).str();
|
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())
|
if (std::cin.eof())
|
||||||
return true;
|
return true;
|
||||||
if (!command_line::is_yes(accepted))
|
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
|
// prompt is there is no payment id and confirmation is required
|
||||||
if (!payment_id_seen && m_wallet->confirm_missing_payment_id())
|
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())
|
if (std::cin.eof())
|
||||||
return true;
|
return true;
|
||||||
if (!command_line::is_yes(accepted))
|
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_sent) %
|
||||||
print_money(total_fee);
|
print_money(total_fee);
|
||||||
}
|
}
|
||||||
std::string accepted = command_line::input_line(prompt.str());
|
std::string accepted = input_line(prompt.str());
|
||||||
if (std::cin.eof())
|
if (std::cin.eof())
|
||||||
return true;
|
return true;
|
||||||
if (!command_line::is_yes(accepted))
|
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;
|
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();
|
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)
|
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>]",
|
"monero-wallet-cli [--wallet-file=<file>|--generate-new-wallet=<file>] [<COMMAND>]",
|
||||||
desc_params,
|
desc_params,
|
||||||
positional_options,
|
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"
|
"monero-wallet-cli.log"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -108,6 +108,7 @@ if (NOT BUILD_GUI_DEPS)
|
|||||||
PRIVATE
|
PRIVATE
|
||||||
wallet
|
wallet
|
||||||
epee
|
epee
|
||||||
|
${EPEE_READLINE}
|
||||||
rpc
|
rpc
|
||||||
cryptonote_core
|
cryptonote_core
|
||||||
cncrypto
|
cncrypto
|
||||||
|
@ -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);
|
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 testnet = command_line::get_arg(vm, opts.testnet);
|
||||||
const bool restricted = command_line::get_arg(vm, opts.restricted);
|
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_host = command_line::get_arg(vm, opts.daemon_host);
|
||||||
auto daemon_port = command_line::get_arg(vm, opts.daemon_port);
|
auto daemon_port = command_line::get_arg(vm, opts.daemon_port);
|
||||||
|
|
||||||
if (!daemon_address.empty() && !daemon_host.empty() && 0 != daemon_port)
|
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"));
|
||||||
tools::fail_msg_writer() << tools::wallet2::tr("can't specify daemon host or port more than once");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::optional<epee::net_utils::http::login> login{};
|
boost::optional<epee::net_utils::http::login> login{};
|
||||||
if (command_line::has_arg(vm, opts.daemon_login))
|
if (command_line::has_arg(vm, opts.daemon_login))
|
||||||
{
|
{
|
||||||
auto parsed = tools::login::parse(
|
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)
|
if (!parsed)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@ -180,12 +179,11 @@ std::unique_ptr<tools::wallet2> make_basic(const boost::program_options::variabl
|
|||||||
return wallet;
|
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))
|
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");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("can't specify more than one of --password and --password-file"));
|
||||||
return boost::none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command_line::has_arg(vm, opts.password))
|
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;
|
std::string password;
|
||||||
bool r = epee::file_io_utils::load_file_to_string(command_line::get_arg(vm, opts.password_file),
|
bool r = epee::file_io_utils::load_file_to_string(command_line::get_arg(vm, opts.password_file),
|
||||||
password);
|
password);
|
||||||
if (!r)
|
THROW_WALLET_EXCEPTION_IF(!r, tools::error::wallet_internal_error, tools::wallet2::tr("the password file specified could not be read"));
|
||||||
{
|
|
||||||
tools::fail_msg_writer() << tools::wallet2::tr("the password file specified could not be read");
|
|
||||||
return boost::none;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove line breaks the user might have inserted
|
// Remove line breaks the user might have inserted
|
||||||
boost::trim_right_if(password, boost::is_any_of("\r\n"));
|
boost::trim_right_if(password, boost::is_any_of("\r\n"));
|
||||||
return {tools::password_container{std::move(password)}};
|
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);
|
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 {
|
const auto do_generate = [&]() -> bool {
|
||||||
std::string buf;
|
std::string buf;
|
||||||
if (!epee::file_io_utils::load_file_to_string(json_file, 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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
rapidjson::Document json;
|
rapidjson::Document json;
|
||||||
if (json.Parse(buf.c_str()).HasParseError()) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, version, unsigned, Uint, true, 0);
|
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, version, unsigned, Uint, true, 0);
|
||||||
const int current_version = 1;
|
const int current_version = 1;
|
||||||
if (field_version > current_version) {
|
THROW_WALLET_EXCEPTION_IF(field_version > current_version, tools::error::wallet_internal_error,
|
||||||
tools::fail_msg_writer() << boost::format(tools::wallet2::tr("Version %u too new, we can only grok up to %u")) % field_version % current_version;
|
((boost::format(tools::wallet2::tr("Version %u too new, we can only grok up to %u")) % field_version % current_version)).str());
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
GET_FIELD_FROM_JSON_RETURN_ON_ERROR(json, filename, std::string, String, true, std::string());
|
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;
|
cryptonote::blobdata viewkey_data;
|
||||||
if(!epee::string_tools::parse_hexstr_to_binbuff(field_viewkey, viewkey_data) || viewkey_data.size() != sizeof(crypto::secret_key))
|
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");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to parse view key secret key"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
viewkey = *reinterpret_cast<const crypto::secret_key*>(viewkey_data.data());
|
viewkey = *reinterpret_cast<const crypto::secret_key*>(viewkey_data.data());
|
||||||
crypto::public_key pkey;
|
crypto::public_key pkey;
|
||||||
if (!crypto::secret_key_to_public_key(viewkey, pkey)) {
|
if (!crypto::secret_key_to_public_key(viewkey, pkey)) {
|
||||||
tools::fail_msg_writer() << tools::wallet2::tr("failed to verify view key secret key");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify view key secret key"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,14 +262,12 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
|
|||||||
cryptonote::blobdata spendkey_data;
|
cryptonote::blobdata spendkey_data;
|
||||||
if(!epee::string_tools::parse_hexstr_to_binbuff(field_spendkey, spendkey_data) || spendkey_data.size() != sizeof(crypto::secret_key))
|
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");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to parse spend key secret key"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
|
spendkey = *reinterpret_cast<const crypto::secret_key*>(spendkey_data.data());
|
||||||
crypto::public_key pkey;
|
crypto::public_key pkey;
|
||||||
if (!crypto::secret_key_to_public_key(spendkey, pkey)) {
|
if (!crypto::secret_key_to_public_key(spendkey, pkey)) {
|
||||||
tools::fail_msg_writer() << tools::wallet2::tr("failed to verify spend key secret key");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify spend key secret key"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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))
|
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");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("Electrum-style word list failed verification"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
restore_deterministic_wallet = true;
|
restore_deterministic_wallet = true;
|
||||||
|
|
||||||
@ -309,13 +296,11 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
|
|||||||
// compatibility checks
|
// compatibility checks
|
||||||
if (!field_seed_found && !field_viewkey_found && !field_spendkey_found)
|
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");
|
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"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (field_seed_found && (field_viewkey_found || field_spendkey_found))
|
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");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("Both Electrum-style word list and private key(s) specified"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// if an address was given, we check keys against it, and deduce the spend
|
// 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;
|
cryptonote::address_parse_info info;
|
||||||
if(!get_account_address_from_str(info, testnet, field_address))
|
if(!get_account_address_from_str(info, testnet, field_address))
|
||||||
{
|
{
|
||||||
tools::fail_msg_writer() << tools::wallet2::tr("invalid address");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("invalid address"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (field_viewkey_found)
|
if (field_viewkey_found)
|
||||||
{
|
{
|
||||||
crypto::public_key pkey;
|
crypto::public_key pkey;
|
||||||
if (!crypto::secret_key_to_public_key(viewkey, pkey)) {
|
if (!crypto::secret_key_to_public_key(viewkey, pkey)) {
|
||||||
tools::fail_msg_writer() << tools::wallet2::tr("failed to verify view key secret key");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify view key secret key"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (info.address.m_view_public_key != pkey) {
|
if (info.address.m_view_public_key != pkey) {
|
||||||
tools::fail_msg_writer() << tools::wallet2::tr("view key does not match standard address");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("view key does not match standard address"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (field_spendkey_found)
|
if (field_spendkey_found)
|
||||||
{
|
{
|
||||||
crypto::public_key pkey;
|
crypto::public_key pkey;
|
||||||
if (!crypto::secret_key_to_public_key(spendkey, pkey)) {
|
if (!crypto::secret_key_to_public_key(spendkey, pkey)) {
|
||||||
tools::fail_msg_writer() << tools::wallet2::tr("failed to verify spend key secret key");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify spend key secret key"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
if (info.address.m_spend_public_key != pkey) {
|
if (info.address.m_spend_public_key != pkey) {
|
||||||
tools::fail_msg_writer() << tools::wallet2::tr("spend key does not match standard address");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("spend key does not match standard address"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool deprecated_wallet = restore_deterministic_wallet && ((old_language == crypto::ElectrumWords::old_language_name) ||
|
const bool deprecated_wallet = restore_deterministic_wallet && ((old_language == crypto::ElectrumWords::old_language_name) ||
|
||||||
crypto::ElectrumWords::get_is_old_style_seed(field_seed));
|
crypto::ElectrumWords::get_is_old_style_seed(field_seed));
|
||||||
if (deprecated_wallet) {
|
THROW_WALLET_EXCEPTION_IF(deprecated_wallet, tools::error::wallet_internal_error,
|
||||||
tools::fail_msg_writer() << tools::wallet2::tr("Cannot create deprecated wallets from JSON");
|
tools::wallet2::tr("Cannot create deprecated wallets from JSON"));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
wallet->set_refresh_from_block_height(field_scan_from_height);
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -378,8 +356,7 @@ std::unique_ptr<tools::wallet2> generate_from_json(const std::string& json_file,
|
|||||||
{
|
{
|
||||||
cryptonote::account_public_address address;
|
cryptonote::account_public_address address;
|
||||||
if (!crypto::secret_key_to_public_key(viewkey, address.m_view_public_key)) {
|
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");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify view key secret key"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (field_spendkey.empty())
|
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;
|
cryptonote::address_parse_info info;
|
||||||
if(!get_account_address_from_str(info, testnet, field_address))
|
if(!get_account_address_from_str(info, testnet, field_address))
|
||||||
{
|
{
|
||||||
tools::fail_msg_writer() << tools::wallet2::tr("failed to parse address: ") << field_address;
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, std::string(tools::wallet2::tr("failed to parse address: ")) + field_address);
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
address.m_spend_public_key = info.address.m_spend_public_key;
|
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
|
else
|
||||||
{
|
{
|
||||||
if (!crypto::secret_key_to_public_key(spendkey, address.m_spend_public_key)) {
|
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");
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, tools::wallet2::tr("failed to verify spend key secret key"));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
wallet->generate(field_filename, field_password, address, spendkey, viewkey);
|
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)
|
catch (const std::exception& e)
|
||||||
{
|
{
|
||||||
tools::fail_msg_writer() << tools::wallet2::tr("failed to generate new wallet: ") << e.what();
|
THROW_WALLET_EXCEPTION(tools::error::wallet_internal_error, std::string(tools::wallet2::tr("failed to generate new wallet: ")) + e.what());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
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);
|
command_line::add_arg(desc_params, opts.restricted);
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<password_container> wallet2::password_prompt(const bool new_password)
|
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)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
const options opts{};
|
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(
|
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{};
|
const options opts{};
|
||||||
auto pwd = get_password(vm, opts, false);
|
auto pwd = get_password(vm, opts, password_prompter, false);
|
||||||
if (!pwd)
|
if (!pwd)
|
||||||
{
|
{
|
||||||
return {nullptr, password_container{}};
|
return {nullptr, password_container{}};
|
||||||
}
|
}
|
||||||
auto wallet = make_basic(vm, opts);
|
auto wallet = make_basic(vm, opts, password_prompter);
|
||||||
if (wallet)
|
if (wallet)
|
||||||
{
|
{
|
||||||
wallet->load(wallet_file, pwd->password());
|
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)};
|
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{};
|
const options opts{};
|
||||||
auto pwd = get_password(vm, opts, true);
|
auto pwd = get_password(vm, opts, password_prompter, true);
|
||||||
if (!pwd)
|
if (!pwd)
|
||||||
{
|
{
|
||||||
return {nullptr, password_container{}};
|
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{};
|
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;
|
std::string data;
|
||||||
bool r = epee::file_io_utils::load_file_to_string(filename, data);
|
bool r = epee::file_io_utils::load_file_to_string(filename, data);
|
||||||
|
|
||||||
if (!r)
|
THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, std::string(tr("failed to read file ")) + filename);
|
||||||
{
|
|
||||||
fail_msg_writer() << tr("failed to read file ") << filename;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const size_t magiclen = strlen(KEY_IMAGE_EXPORT_FILE_MAGIC);
|
const size_t magiclen = strlen(KEY_IMAGE_EXPORT_FILE_MAGIC);
|
||||||
if (data.size() < magiclen || memcmp(data.data(), KEY_IMAGE_EXPORT_FILE_MAGIC, magiclen))
|
if (data.size() < magiclen || memcmp(data.data(), KEY_IMAGE_EXPORT_FILE_MAGIC, magiclen))
|
||||||
{
|
{
|
||||||
fail_msg_writer() << "Bad key image export file magic in " << filename;
|
THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Bad key image export file magic in ") + filename);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
@ -6543,31 +6501,22 @@ uint64_t wallet2::import_key_images(const std::string &filename, uint64_t &spent
|
|||||||
}
|
}
|
||||||
catch (const std::exception &e)
|
catch (const std::exception &e)
|
||||||
{
|
{
|
||||||
fail_msg_writer() << "Failed to decrypt " << filename << ": " << e.what();
|
THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string("Failed to decrypt ") + filename + ": " + e.what());
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t headerlen = 2 * sizeof(crypto::public_key);
|
const size_t headerlen = 2 * sizeof(crypto::public_key);
|
||||||
if (data.size() < headerlen)
|
THROW_WALLET_EXCEPTION_IF(data.size() < headerlen, error::wallet_internal_error, std::string("Bad data size from file ") + filename);
|
||||||
{
|
|
||||||
fail_msg_writer() << "Bad data size from file " << filename;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
const crypto::public_key &public_spend_key = *(const crypto::public_key*)&data[0];
|
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 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;
|
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)
|
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";
|
THROW_WALLET_EXCEPTION(error::wallet_internal_error, std::string( "Key images from ") + filename + " are for a different account");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature);
|
const size_t record_size = sizeof(crypto::key_image) + sizeof(crypto::signature);
|
||||||
if ((data.size() - headerlen) % record_size)
|
THROW_WALLET_EXCEPTION_IF((data.size() - headerlen) % record_size,
|
||||||
{
|
error::wallet_internal_error, std::string("Bad data size from file ") + filename);
|
||||||
fail_msg_writer() << "Bad data size from file " << filename;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
size_t nki = (data.size() - headerlen) / record_size;
|
size_t nki = (data.size() - headerlen) / record_size;
|
||||||
|
|
||||||
std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
|
std::vector<std::pair<crypto::key_image, crypto::signature>> ski;
|
||||||
|
@ -155,21 +155,18 @@ namespace tools
|
|||||||
static bool has_testnet_option(const boost::program_options::variables_map& vm);
|
static bool has_testnet_option(const boost::program_options::variables_map& vm);
|
||||||
static void init_options(boost::program_options::options_description& desc_params);
|
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.
|
//! 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.
|
//! Uses stdin and stdout. Returns a wallet2 and password for `wallet_file` if no errors.
|
||||||
static std::pair<std::unique_ptr<wallet2>, password_container>
|
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.
|
//! 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.
|
//! 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);
|
static bool verify_password(const std::string& keys_file_name, const std::string& password, bool watch_only);
|
||||||
|
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
#include <boost/format.hpp>
|
#include <boost/format.hpp>
|
||||||
#include "common/i18n.h"
|
#include "common/i18n.h"
|
||||||
#include "common/scoped_message_writer.h"
|
|
||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "misc_log_ex.h"
|
#include "misc_log_ex.h"
|
||||||
#include "string_tools.h"
|
#include "string_tools.h"
|
||||||
@ -50,6 +49,20 @@
|
|||||||
#define DEFAULT_MAX_CONCURRENCY 0
|
#define DEFAULT_MAX_CONCURRENCY 0
|
||||||
#endif
|
#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
|
namespace wallet_args
|
||||||
{
|
{
|
||||||
@ -73,6 +86,7 @@ namespace wallet_args
|
|||||||
const char* const usage,
|
const char* const usage,
|
||||||
boost::program_options::options_description desc_params,
|
boost::program_options::options_description desc_params,
|
||||||
const boost::program_options::positional_options_description& positional_options,
|
const boost::program_options::positional_options_description& positional_options,
|
||||||
|
const std::function<void(const std::string&, bool)> &print,
|
||||||
const char *default_log_name,
|
const char *default_log_name,
|
||||||
bool log_to_console)
|
bool log_to_console)
|
||||||
|
|
||||||
@ -118,16 +132,16 @@ namespace wallet_args
|
|||||||
|
|
||||||
if (command_line::get_arg(vm, command_line::arg_help))
|
if (command_line::get_arg(vm, command_line::arg_help))
|
||||||
{
|
{
|
||||||
tools::msg_writer() << "Monero '" << MONERO_RELEASE_NAME << "' (v" << MONERO_VERSION_FULL << ")" << ENDL;
|
Print(print) << "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) << wallet_args::tr("This is the command line monero wallet. It needs to connect to a monero\n"
|
||||||
"daemon to work correctly.") << ENDL;
|
"daemon to work correctly.") << ENDL;
|
||||||
tools::msg_writer() << wallet_args::tr("Usage:") << ENDL << " " << usage;
|
Print(print) << wallet_args::tr("Usage:") << ENDL << " " << usage;
|
||||||
tools::msg_writer() << desc_all;
|
Print(print) << desc_all;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
else if (command_line::get_arg(vm, command_line::arg_version))
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +156,7 @@ namespace wallet_args
|
|||||||
}
|
}
|
||||||
else
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -167,14 +181,15 @@ namespace wallet_args
|
|||||||
if(command_line::has_arg(vm, arg_max_concurrency))
|
if(command_line::has_arg(vm, arg_max_concurrency))
|
||||||
tools::set_max_concurrency(command_line::get_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))
|
if (!command_line::is_arg_defaulted(vm, arg_log_level))
|
||||||
MINFO("Setting log level = " << command_line::get_arg(vm, arg_log_level));
|
MINFO("Setting log level = " << command_line::get_arg(vm, arg_log_level));
|
||||||
else
|
else
|
||||||
MINFO("Setting log levels = " << getenv("MONERO_LOGS"));
|
MINFO("Setting log levels = " << getenv("MONERO_LOGS"));
|
||||||
MINFO(wallet_args::tr("Logging to: ") << log_path);
|
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)};
|
return {std::move(vm)};
|
||||||
}
|
}
|
||||||
|
@ -50,5 +50,6 @@ namespace wallet_args
|
|||||||
const char* const usage,
|
const char* const usage,
|
||||||
boost::program_options::options_description desc_params,
|
boost::program_options::options_description desc_params,
|
||||||
const boost::program_options::positional_options_description& positional_options,
|
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);
|
const char *default_log_name, bool log_to_console = false);
|
||||||
}
|
}
|
||||||
|
@ -765,6 +765,12 @@ namespace tools
|
|||||||
#define STRINGIZE_DETAIL(x) #x
|
#define STRINGIZE_DETAIL(x) #x
|
||||||
#define STRINGIZE(x) STRINGIZE_DETAIL(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, ...) \
|
#define THROW_WALLET_EXCEPTION_IF(cond, err_type, ...) \
|
||||||
if (cond) \
|
if (cond) \
|
||||||
{ \
|
{ \
|
||||||
|
@ -38,6 +38,7 @@ using namespace epee;
|
|||||||
#include "wallet/wallet_args.h"
|
#include "wallet/wallet_args.h"
|
||||||
#include "common/command_line.h"
|
#include "common/command_line.h"
|
||||||
#include "common/i18n.h"
|
#include "common/i18n.h"
|
||||||
|
#include "common/scoped_message_writer.h"
|
||||||
#include "cryptonote_basic/cryptonote_format_utils.h"
|
#include "cryptonote_basic/cryptonote_format_utils.h"
|
||||||
#include "cryptonote_basic/account.h"
|
#include "cryptonote_basic/account.h"
|
||||||
#include "wallet_rpc_server_commands_defs.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"};
|
const command_line::arg_descriptor<std::string> arg_wallet_dir = {"wallet-dir", "Directory for newly created wallets"};
|
||||||
|
|
||||||
constexpr const char default_rpc_username[] = "monero";
|
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
|
namespace tools
|
||||||
@ -131,7 +142,7 @@ namespace tools
|
|||||||
walvars = m_wallet;
|
walvars = m_wallet;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
tmpwal = tools::wallet2::make_dummy(*m_vm);
|
tmpwal = tools::wallet2::make_dummy(*m_vm, password_prompter);
|
||||||
walvars = tmpwal.get();
|
walvars = tmpwal.get();
|
||||||
}
|
}
|
||||||
boost::optional<epee::net_utils::http::login> http_login{};
|
boost::optional<epee::net_utils::http::login> http_login{};
|
||||||
@ -1798,7 +1809,7 @@ namespace tools
|
|||||||
command_line::add_arg(desc, arg_password);
|
command_line::add_arg(desc, arg_password);
|
||||||
po::store(po::parse_command_line(argc, argv, desc), vm2);
|
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)
|
if (!wal)
|
||||||
{
|
{
|
||||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||||
@ -1872,7 +1883,7 @@ namespace tools
|
|||||||
}
|
}
|
||||||
std::unique_ptr<tools::wallet2> wal = nullptr;
|
std::unique_ptr<tools::wallet2> wal = nullptr;
|
||||||
try {
|
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)
|
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>]",
|
"monero-wallet-rpc [--wallet-file=<file>|--generate-from-json=<file>|--wallet-dir=<directory>] [--rpc-bind-port=<port>]",
|
||||||
desc_params,
|
desc_params,
|
||||||
po::positional_options_description(),
|
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",
|
"monero-wallet-rpc.log",
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
@ -2007,11 +2019,19 @@ int main(int argc, char** argv) {
|
|||||||
LOG_PRINT_L0(tools::wallet_rpc_server::tr("Loading wallet..."));
|
LOG_PRINT_L0(tools::wallet_rpc_server::tr("Loading wallet..."));
|
||||||
if(!wallet_file.empty())
|
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
|
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)
|
if (!wal)
|
||||||
{
|
{
|
||||||
|
@ -79,7 +79,7 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
po::options_description desc("Allowed options");
|
po::options_description desc("Allowed options");
|
||||||
// tools::get_default_data_dir() can't be called during static initialization
|
// tools::get_default_data_dir() can't be called during static initialization
|
||||||
command_line::add_arg(desc, command_line::arg_data_dir, tools::get_default_data_dir());
|
command_line::add_arg(desc, cryptonote::arg_data_dir, tools::get_default_data_dir());
|
||||||
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<tests::proxy_core> >::init_options(desc);
|
nodetool::node_server<cryptonote::t_cryptonote_protocol_handler<tests::proxy_core> >::init_options(desc);
|
||||||
|
|
||||||
po::variables_map vm;
|
po::variables_map vm;
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "include_base_utils.h"
|
#include "include_base_utils.h"
|
||||||
#include "common/command_line.h"
|
|
||||||
#include "file_io_utils.h"
|
#include "file_io_utils.h"
|
||||||
#include "cryptonote_protocol/blobdatatype.h"
|
#include "cryptonote_protocol/blobdatatype.h"
|
||||||
#include "cryptonote_basic/cryptonote_basic.h"
|
#include "cryptonote_basic/cryptonote_basic.h"
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "include_base_utils.h"
|
#include "include_base_utils.h"
|
||||||
#include "common/command_line.h"
|
|
||||||
#include "file_io_utils.h"
|
#include "file_io_utils.h"
|
||||||
#include "cryptonote_protocol/blobdatatype.h"
|
#include "cryptonote_protocol/blobdatatype.h"
|
||||||
#include "cryptonote_basic/cryptonote_basic.h"
|
#include "cryptonote_basic/cryptonote_basic.h"
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "include_base_utils.h"
|
#include "include_base_utils.h"
|
||||||
#include "common/command_line.h"
|
|
||||||
#include "file_io_utils.h"
|
#include "file_io_utils.h"
|
||||||
#include "cryptonote_protocol/blobdatatype.h"
|
#include "cryptonote_protocol/blobdatatype.h"
|
||||||
#include "cryptonote_basic/cryptonote_basic.h"
|
#include "cryptonote_basic/cryptonote_basic.h"
|
||||||
|
@ -27,7 +27,6 @@
|
|||||||
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
#include "include_base_utils.h"
|
#include "include_base_utils.h"
|
||||||
#include "common/command_line.h"
|
|
||||||
#include "file_io_utils.h"
|
#include "file_io_utils.h"
|
||||||
#include "cryptonote_protocol/blobdatatype.h"
|
#include "cryptonote_protocol/blobdatatype.h"
|
||||||
#include "cryptonote_basic/cryptonote_basic.h"
|
#include "cryptonote_basic/cryptonote_basic.h"
|
||||||
|
@ -53,7 +53,7 @@ int main(int argc, char** argv)
|
|||||||
|
|
||||||
po::options_description desc_options("Command line options");
|
po::options_description desc_options("Command line options");
|
||||||
const command_line::arg_descriptor<std::string> arg_data_dir = {"data-dir", "Data files directory", "", true};
|
const command_line::arg_descriptor<std::string> arg_data_dir = {"data-dir", "Data files directory", "", true};
|
||||||
command_line::add_arg(desc_options, command_line::arg_data_dir, "");
|
command_line::add_arg(desc_options, arg_data_dir, "");
|
||||||
|
|
||||||
po::variables_map vm;
|
po::variables_map vm;
|
||||||
bool r = command_line::handle_error_helper(desc_options, [&]()
|
bool r = command_line::handle_error_helper(desc_options, [&]()
|
||||||
|
Loading…
Reference in New Issue
Block a user