From 7dd7a3b7912010834b9b156058ceeaa890978a1a Mon Sep 17 00:00:00 2001 From: Joel Date: Tue, 19 Feb 2019 14:13:01 +0100 Subject: [PATCH 1/4] Add generate_from_keys RPC method --- src/wallet/wallet_rpc_server.cpp | 166 +++++++++++++++++++ src/wallet/wallet_rpc_server.h | 2 + src/wallet/wallet_rpc_server_commands_defs.h | 33 ++++ 3 files changed, 201 insertions(+) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index c87c2fca6..a23391a9b 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -3129,6 +3129,172 @@ namespace tools } } //------------------------------------------------------------------------------------------------------------------------------ + bool wallet_rpc_server::on_generate_from_keys(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request &req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response &res, epee::json_rpc::error &er, const connection_context *ctx) + { + if (m_wallet_dir.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_NO_WALLET_DIR; + er.message = "No wallet dir configured"; + return false; + } + + // early check for mandatory fields + if (req.filename.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "field 'filename' is mandatory. Please provide a filename to save the restored wallet to."; + return false; + } + if (req.spendkey.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "field 'spendkey' is mandatory. Please provide a spend key you want to restore from."; + return false; + } + if (req.viewkey.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "field 'viewkey' is mandatory. Please provide a view key you want to restore from."; + return false; + } + if (req.address.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "field 'address' is mandatory. Please provide a public address."; + return false; + } + + namespace po = boost::program_options; + po::variables_map vm2; + const char *ptr = strchr(req.filename.c_str(), '/'); + #ifdef _WIN32 + if (!ptr) + ptr = strchr(req.filename.c_str(), '\\'); + if (!ptr) + ptr = strchr(req.filename.c_str(), ':'); + #endif + if (ptr) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Invalid filename"; + return false; + } + std::string wallet_file = m_wallet_dir + "/" + req.filename; + // check if wallet file already exists + if (!wallet_file.empty()) + { + try + { + boost::system::error_code ignored_ec; + THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(wallet_file, ignored_ec), error::file_exists, wallet_file); + } + catch (const std::exception &e) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Wallet already exists."; + return false; + } + } + + { + po::options_description desc("dummy"); + const command_line::arg_descriptor arg_password = {"password", "password"}; + const char *argv[4]; + int argc = 3; + argv[0] = "wallet-rpc"; + argv[1] = "--password"; + argv[2] = req.password.c_str(); + argv[3] = NULL; + vm2 = *m_vm; + command_line::add_arg(desc, arg_password); + po::store(po::parse_command_line(argc, argv, desc), vm2); + } + + auto rc = tools::wallet2::make_new(vm2, true, nullptr); + std::unique_ptr wal; + wal = std::move(rc.first); + if (!wal) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to create wallet"; + return false; + } + + cryptonote::address_parse_info info; + if(!get_account_address_from_str(info, wal->nettype(), req.address)) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to parse public address"; + return false; + } + + epee::wipeable_string password = rc.second.password(); + epee::wipeable_string spendkey_string = req.spendkey; + crypto::secret_key spendkey; + if (!spendkey_string.hex_to_pod(unwrap(unwrap(spendkey)))) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to parse spend key secret key"; + return false; + } + epee::wipeable_string viewkey_string = req.viewkey; + crypto::secret_key viewkey; + if (!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey)))) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to parse view key secret key"; + return false; + } + + try + { + wal->generate(wallet_file, std::move(rc.second).password(), info.address, spendkey, viewkey, false); + MINFO("Wallet has been restored.\n"); + } + catch (const std::exception &e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + + if (!wal) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to generate wallet"; + return false; + } + + // set blockheight if given + try + { + wal->set_refresh_from_block_height(req.restore_height); + wal->rewrite(wallet_file, password); + } + catch (const std::exception &e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + + if (m_wallet) + { + try + { + m_wallet->store(); + } + catch (const std::exception &e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + delete m_wallet; + } + m_wallet = wal.release(); + res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + res.info = "Wallet has been restored successfully."; + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_restore_deterministic_wallet(const wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::request &req, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::response &res, epee::json_rpc::error &er, const connection_context *ctx) { if (m_wallet_dir.empty()) diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 1a54e4c79..5f3c332e2 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -137,6 +137,7 @@ namespace tools MAP_JON_RPC_WE("open_wallet", on_open_wallet, wallet_rpc::COMMAND_RPC_OPEN_WALLET) MAP_JON_RPC_WE("close_wallet", on_close_wallet, wallet_rpc::COMMAND_RPC_CLOSE_WALLET) MAP_JON_RPC_WE("change_wallet_password", on_change_wallet_password, wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD) + MAP_JON_RPC_WE("generate_from_keys", on_generate_from_keys, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS) MAP_JON_RPC_WE("restore_deterministic_wallet", on_restore_deterministic_wallet, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET) MAP_JON_RPC_WE("is_multisig", on_is_multisig, wallet_rpc::COMMAND_RPC_IS_MULTISIG) MAP_JON_RPC_WE("prepare_multisig", on_prepare_multisig, wallet_rpc::COMMAND_RPC_PREPARE_MULTISIG) @@ -216,6 +217,7 @@ namespace tools bool on_open_wallet(const wallet_rpc::COMMAND_RPC_OPEN_WALLET::request& req, wallet_rpc::COMMAND_RPC_OPEN_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_close_wallet(const wallet_rpc::COMMAND_RPC_CLOSE_WALLET::request& req, wallet_rpc::COMMAND_RPC_CLOSE_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_change_wallet_password(const wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD::request& req, wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); + bool on_generate_from_keys(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request& req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_restore_deterministic_wallet(const wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::request& req, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_is_multisig(const wallet_rpc::COMMAND_RPC_IS_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_IS_MULTISIG::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_prepare_multisig(const wallet_rpc::COMMAND_RPC_PREPARE_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_PREPARE_MULTISIG::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index f0c1a4e9d..8c46121e4 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -1934,6 +1934,39 @@ namespace wallet_rpc }; }; + struct COMMAND_RPC_GENERATE_FROM_KEYS + { + struct request + { + uint64_t restore_height; + std::string filename; + std::string address; + std::string spendkey; + std::string viewkey; + std::string password; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE_OPT(restore_height, (uint64_t)0) + KV_SERIALIZE(filename) + KV_SERIALIZE(address) + KV_SERIALIZE(spendkey) + KV_SERIALIZE(viewkey) + KV_SERIALIZE(password) + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::string address; + std::string info; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(address) + KV_SERIALIZE(info) + END_KV_SERIALIZE_MAP() + }; + }; + struct COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET { struct request From acb14c10796e596a3b16ea306cbf76499f8a7224 Mon Sep 17 00:00:00 2001 From: Joel Date: Tue, 19 Feb 2019 14:30:35 +0100 Subject: [PATCH 2/4] Add generate_from_view_key RPC method --- src/wallet/wallet_rpc_server.cpp | 152 +++++++++++++++++++ src/wallet/wallet_rpc_server.h | 2 + src/wallet/wallet_rpc_server_commands_defs.h | 31 ++++ 3 files changed, 185 insertions(+) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index a23391a9b..f29827034 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -3129,6 +3129,158 @@ namespace tools } } //------------------------------------------------------------------------------------------------------------------------------ + bool wallet_rpc_server::on_generate_from_view_key(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_VIEW_KEY::request &req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_VIEW_KEY::response &res, epee::json_rpc::error &er, const connection_context *ctx) + { + if (m_wallet_dir.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_NO_WALLET_DIR; + er.message = "No wallet dir configured"; + return false; + } + + // early check for mandatory fields + if (req.filename.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "field 'filename' is mandatory. Please provide a filename to save the restored wallet to."; + return false; + } + if (req.viewkey.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "field 'viewkey' is mandatory. Please provide a view key you want to restore from."; + return false; + } + if (req.address.empty()) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "field 'address' is mandatory. Please provide a public address."; + return false; + } + + namespace po = boost::program_options; + po::variables_map vm2; + const char *ptr = strchr(req.filename.c_str(), '/'); + #ifdef _WIN32 + if (!ptr) + ptr = strchr(req.filename.c_str(), '\\'); + if (!ptr) + ptr = strchr(req.filename.c_str(), ':'); + #endif + if (ptr) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Invalid filename"; + return false; + } + std::string wallet_file = m_wallet_dir + "/" + req.filename; + // check if wallet file already exists + if (!wallet_file.empty()) + { + try + { + boost::system::error_code ignored_ec; + THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(wallet_file, ignored_ec), error::file_exists, wallet_file); + } + catch (const std::exception &e) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Wallet already exists."; + return false; + } + } + + { + po::options_description desc("dummy"); + const command_line::arg_descriptor arg_password = {"password", "password"}; + const char *argv[4]; + int argc = 3; + argv[0] = "wallet-rpc"; + argv[1] = "--password"; + argv[2] = req.password.c_str(); + argv[3] = NULL; + vm2 = *m_vm; + command_line::add_arg(desc, arg_password); + po::store(po::parse_command_line(argc, argv, desc), vm2); + } + + auto rc = tools::wallet2::make_new(vm2, true, nullptr); + std::unique_ptr wal; + wal = std::move(rc.first); + if (!wal) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to create wallet"; + return false; + } + + cryptonote::address_parse_info info; + if(!get_account_address_from_str(info, wal->nettype(), req.address)) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to parse public address"; + return false; + } + + epee::wipeable_string password = rc.second.password(); + epee::wipeable_string viewkey_string = req.viewkey; + crypto::secret_key viewkey; + if (!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey)))) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to parse view key secret key"; + return false; + } + + try + { + wal->generate(wallet_file, std::move(rc.second).password(), info.address, viewkey, false); + MINFO("Wallet has been restored.\n"); + } + catch (const std::exception &e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + + if (!wal) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to generate wallet"; + return false; + } + + // set blockheight if given + try + { + wal->set_refresh_from_block_height(req.restore_height); + wal->rewrite(wallet_file, password); + } + catch (const std::exception &e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + + if (m_wallet) + { + try + { + m_wallet->store(); + } + catch (const std::exception &e) + { + handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); + return false; + } + delete m_wallet; + } + m_wallet = wal.release(); + res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); + res.info = "Wallet has been restored successfully."; + return true; + } + //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_generate_from_keys(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request &req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response &res, epee::json_rpc::error &er, const connection_context *ctx) { if (m_wallet_dir.empty()) diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 5f3c332e2..45491c90a 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -137,6 +137,7 @@ namespace tools MAP_JON_RPC_WE("open_wallet", on_open_wallet, wallet_rpc::COMMAND_RPC_OPEN_WALLET) MAP_JON_RPC_WE("close_wallet", on_close_wallet, wallet_rpc::COMMAND_RPC_CLOSE_WALLET) MAP_JON_RPC_WE("change_wallet_password", on_change_wallet_password, wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD) + MAP_JON_RPC_WE("generate_from_view_key", on_generate_from_view_key, wallet_rpc::COMMAND_RPC_GENERATE_FROM_VIEW_KEY) MAP_JON_RPC_WE("generate_from_keys", on_generate_from_keys, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS) MAP_JON_RPC_WE("restore_deterministic_wallet", on_restore_deterministic_wallet, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET) MAP_JON_RPC_WE("is_multisig", on_is_multisig, wallet_rpc::COMMAND_RPC_IS_MULTISIG) @@ -217,6 +218,7 @@ namespace tools bool on_open_wallet(const wallet_rpc::COMMAND_RPC_OPEN_WALLET::request& req, wallet_rpc::COMMAND_RPC_OPEN_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_close_wallet(const wallet_rpc::COMMAND_RPC_CLOSE_WALLET::request& req, wallet_rpc::COMMAND_RPC_CLOSE_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_change_wallet_password(const wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD::request& req, wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); + bool on_generate_from_view_key(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_VIEW_KEY::request& req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_VIEW_KEY::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_generate_from_keys(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request& req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_restore_deterministic_wallet(const wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::request& req, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_is_multisig(const wallet_rpc::COMMAND_RPC_IS_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_IS_MULTISIG::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 8c46121e4..8dd13322f 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -1934,6 +1934,37 @@ namespace wallet_rpc }; }; + struct COMMAND_RPC_GENERATE_FROM_VIEW_KEY + { + struct request + { + uint64_t restore_height; + std::string filename; + std::string address; + std::string viewkey; + std::string password; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE_OPT(restore_height, (uint64_t)0) + KV_SERIALIZE(filename) + KV_SERIALIZE(address) + KV_SERIALIZE(viewkey) + KV_SERIALIZE(password) + END_KV_SERIALIZE_MAP() + }; + + struct response + { + std::string address; + std::string info; + + BEGIN_KV_SERIALIZE_MAP() + KV_SERIALIZE(address) + KV_SERIALIZE(info) + END_KV_SERIALIZE_MAP() + }; + }; + struct COMMAND_RPC_GENERATE_FROM_KEYS { struct request From c17c81881b240c389875bf2652b2f3a5d95aa1ab Mon Sep 17 00:00:00 2001 From: Joel Date: Thu, 21 Feb 2019 15:49:32 +0100 Subject: [PATCH 3/4] Remove code duplication --- src/wallet/wallet_rpc_server.cpp | 175 ++----------------- src/wallet/wallet_rpc_server.h | 4 +- src/wallet/wallet_rpc_server_commands_defs.h | 31 ---- 3 files changed, 20 insertions(+), 190 deletions(-) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index f29827034..86ca13416 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -3129,7 +3129,7 @@ namespace tools } } //------------------------------------------------------------------------------------------------------------------------------ - bool wallet_rpc_server::on_generate_from_view_key(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_VIEW_KEY::request &req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_VIEW_KEY::response &res, epee::json_rpc::error &er, const connection_context *ctx) + bool wallet_rpc_server::on_generate_from_view_key(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request &req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response &res, epee::json_rpc::error &er, const connection_context *ctx) { if (m_wallet_dir.empty()) { @@ -3234,7 +3234,22 @@ namespace tools try { - wal->generate(wallet_file, std::move(rc.second).password(), info.address, viewkey, false); + if (!req.spendkey.empty()) + { + epee::wipeable_string spendkey_string = req.spendkey; + crypto::secret_key spendkey; + if (!spendkey_string.hex_to_pod(unwrap(unwrap(spendkey)))) + { + er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; + er.message = "Failed to parse spend key secret key"; + return false; + } + wal->generate(wallet_file, std::move(rc.second).password(), info.address, spendkey, viewkey, false); + } + else + { + wal->generate(wallet_file, std::move(rc.second).password(), info.address, viewkey, false); + } MINFO("Wallet has been restored.\n"); } catch (const std::exception &e) @@ -3283,168 +3298,14 @@ namespace tools //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_generate_from_keys(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request &req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response &res, epee::json_rpc::error &er, const connection_context *ctx) { - if (m_wallet_dir.empty()) - { - er.code = WALLET_RPC_ERROR_CODE_NO_WALLET_DIR; - er.message = "No wallet dir configured"; - return false; - } - // early check for mandatory fields - if (req.filename.empty()) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "field 'filename' is mandatory. Please provide a filename to save the restored wallet to."; - return false; - } if (req.spendkey.empty()) { er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; er.message = "field 'spendkey' is mandatory. Please provide a spend key you want to restore from."; return false; } - if (req.viewkey.empty()) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "field 'viewkey' is mandatory. Please provide a view key you want to restore from."; - return false; - } - if (req.address.empty()) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "field 'address' is mandatory. Please provide a public address."; - return false; - } - - namespace po = boost::program_options; - po::variables_map vm2; - const char *ptr = strchr(req.filename.c_str(), '/'); - #ifdef _WIN32 - if (!ptr) - ptr = strchr(req.filename.c_str(), '\\'); - if (!ptr) - ptr = strchr(req.filename.c_str(), ':'); - #endif - if (ptr) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "Invalid filename"; - return false; - } - std::string wallet_file = m_wallet_dir + "/" + req.filename; - // check if wallet file already exists - if (!wallet_file.empty()) - { - try - { - boost::system::error_code ignored_ec; - THROW_WALLET_EXCEPTION_IF(boost::filesystem::exists(wallet_file, ignored_ec), error::file_exists, wallet_file); - } - catch (const std::exception &e) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "Wallet already exists."; - return false; - } - } - - { - po::options_description desc("dummy"); - const command_line::arg_descriptor arg_password = {"password", "password"}; - const char *argv[4]; - int argc = 3; - argv[0] = "wallet-rpc"; - argv[1] = "--password"; - argv[2] = req.password.c_str(); - argv[3] = NULL; - vm2 = *m_vm; - command_line::add_arg(desc, arg_password); - po::store(po::parse_command_line(argc, argv, desc), vm2); - } - - auto rc = tools::wallet2::make_new(vm2, true, nullptr); - std::unique_ptr wal; - wal = std::move(rc.first); - if (!wal) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "Failed to create wallet"; - return false; - } - - cryptonote::address_parse_info info; - if(!get_account_address_from_str(info, wal->nettype(), req.address)) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "Failed to parse public address"; - return false; - } - - epee::wipeable_string password = rc.second.password(); - epee::wipeable_string spendkey_string = req.spendkey; - crypto::secret_key spendkey; - if (!spendkey_string.hex_to_pod(unwrap(unwrap(spendkey)))) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "Failed to parse spend key secret key"; - return false; - } - epee::wipeable_string viewkey_string = req.viewkey; - crypto::secret_key viewkey; - if (!viewkey_string.hex_to_pod(unwrap(unwrap(viewkey)))) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "Failed to parse view key secret key"; - return false; - } - - try - { - wal->generate(wallet_file, std::move(rc.second).password(), info.address, spendkey, viewkey, false); - MINFO("Wallet has been restored.\n"); - } - catch (const std::exception &e) - { - handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); - return false; - } - - if (!wal) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "Failed to generate wallet"; - return false; - } - - // set blockheight if given - try - { - wal->set_refresh_from_block_height(req.restore_height); - wal->rewrite(wallet_file, password); - } - catch (const std::exception &e) - { - handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); - return false; - } - - if (m_wallet) - { - try - { - m_wallet->store(); - } - catch (const std::exception &e) - { - handle_rpc_exception(std::current_exception(), er, WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR); - return false; - } - delete m_wallet; - } - m_wallet = wal.release(); - res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); - res.info = "Wallet has been restored successfully."; - return true; + return wallet_rpc_server::on_generate_from_view_key(req, res, er, ctx); } //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_restore_deterministic_wallet(const wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::request &req, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::response &res, epee::json_rpc::error &er, const connection_context *ctx) diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index 45491c90a..ccadda21d 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -137,7 +137,7 @@ namespace tools MAP_JON_RPC_WE("open_wallet", on_open_wallet, wallet_rpc::COMMAND_RPC_OPEN_WALLET) MAP_JON_RPC_WE("close_wallet", on_close_wallet, wallet_rpc::COMMAND_RPC_CLOSE_WALLET) MAP_JON_RPC_WE("change_wallet_password", on_change_wallet_password, wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD) - MAP_JON_RPC_WE("generate_from_view_key", on_generate_from_view_key, wallet_rpc::COMMAND_RPC_GENERATE_FROM_VIEW_KEY) + MAP_JON_RPC_WE("generate_from_view_key", on_generate_from_view_key, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS) MAP_JON_RPC_WE("generate_from_keys", on_generate_from_keys, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS) MAP_JON_RPC_WE("restore_deterministic_wallet", on_restore_deterministic_wallet, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET) MAP_JON_RPC_WE("is_multisig", on_is_multisig, wallet_rpc::COMMAND_RPC_IS_MULTISIG) @@ -218,7 +218,7 @@ namespace tools bool on_open_wallet(const wallet_rpc::COMMAND_RPC_OPEN_WALLET::request& req, wallet_rpc::COMMAND_RPC_OPEN_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_close_wallet(const wallet_rpc::COMMAND_RPC_CLOSE_WALLET::request& req, wallet_rpc::COMMAND_RPC_CLOSE_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_change_wallet_password(const wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD::request& req, wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); - bool on_generate_from_view_key(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_VIEW_KEY::request& req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_VIEW_KEY::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); + bool on_generate_from_view_key(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request& req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_generate_from_keys(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request& req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_restore_deterministic_wallet(const wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::request& req, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_is_multisig(const wallet_rpc::COMMAND_RPC_IS_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_IS_MULTISIG::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); diff --git a/src/wallet/wallet_rpc_server_commands_defs.h b/src/wallet/wallet_rpc_server_commands_defs.h index 8dd13322f..8c46121e4 100644 --- a/src/wallet/wallet_rpc_server_commands_defs.h +++ b/src/wallet/wallet_rpc_server_commands_defs.h @@ -1934,37 +1934,6 @@ namespace wallet_rpc }; }; - struct COMMAND_RPC_GENERATE_FROM_VIEW_KEY - { - struct request - { - uint64_t restore_height; - std::string filename; - std::string address; - std::string viewkey; - std::string password; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE_OPT(restore_height, (uint64_t)0) - KV_SERIALIZE(filename) - KV_SERIALIZE(address) - KV_SERIALIZE(viewkey) - KV_SERIALIZE(password) - END_KV_SERIALIZE_MAP() - }; - - struct response - { - std::string address; - std::string info; - - BEGIN_KV_SERIALIZE_MAP() - KV_SERIALIZE(address) - KV_SERIALIZE(info) - END_KV_SERIALIZE_MAP() - }; - }; - struct COMMAND_RPC_GENERATE_FROM_KEYS { struct request From 364516975a3269e6c99aaaa8eb7f0b2da6894a89 Mon Sep 17 00:00:00 2001 From: Joel Date: Sat, 2 Mar 2019 22:32:02 +0100 Subject: [PATCH 4/4] Simplify RPC endpoint, emoving second RPC endpoint generate_from_view_key --- src/wallet/wallet_rpc_server.cpp | 19 ++++--------------- src/wallet/wallet_rpc_server.h | 2 -- 2 files changed, 4 insertions(+), 17 deletions(-) diff --git a/src/wallet/wallet_rpc_server.cpp b/src/wallet/wallet_rpc_server.cpp index 86ca13416..6451e5ce3 100644 --- a/src/wallet/wallet_rpc_server.cpp +++ b/src/wallet/wallet_rpc_server.cpp @@ -3129,7 +3129,7 @@ namespace tools } } //------------------------------------------------------------------------------------------------------------------------------ - bool wallet_rpc_server::on_generate_from_view_key(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request &req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response &res, epee::json_rpc::error &er, const connection_context *ctx) + bool wallet_rpc_server::on_generate_from_keys(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request &req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response &res, epee::json_rpc::error &er, const connection_context *ctx) { if (m_wallet_dir.empty()) { @@ -3245,12 +3245,14 @@ namespace tools return false; } wal->generate(wallet_file, std::move(rc.second).password(), info.address, spendkey, viewkey, false); + res.info = "Wallet has been generated successfully."; } else { wal->generate(wallet_file, std::move(rc.second).password(), info.address, viewkey, false); + res.info = "Watch-only wallet has been generated successfully."; } - MINFO("Wallet has been restored.\n"); + MINFO("Wallet has been generated.\n"); } catch (const std::exception &e) { @@ -3292,22 +3294,9 @@ namespace tools } m_wallet = wal.release(); res.address = m_wallet->get_account().get_public_address_str(m_wallet->nettype()); - res.info = "Wallet has been restored successfully."; return true; } //------------------------------------------------------------------------------------------------------------------------------ - bool wallet_rpc_server::on_generate_from_keys(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request &req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response &res, epee::json_rpc::error &er, const connection_context *ctx) - { - // early check for mandatory fields - if (req.spendkey.empty()) - { - er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR; - er.message = "field 'spendkey' is mandatory. Please provide a spend key you want to restore from."; - return false; - } - return wallet_rpc_server::on_generate_from_view_key(req, res, er, ctx); - } - //------------------------------------------------------------------------------------------------------------------------------ bool wallet_rpc_server::on_restore_deterministic_wallet(const wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::request &req, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::response &res, epee::json_rpc::error &er, const connection_context *ctx) { if (m_wallet_dir.empty()) diff --git a/src/wallet/wallet_rpc_server.h b/src/wallet/wallet_rpc_server.h index ccadda21d..5f3c332e2 100644 --- a/src/wallet/wallet_rpc_server.h +++ b/src/wallet/wallet_rpc_server.h @@ -137,7 +137,6 @@ namespace tools MAP_JON_RPC_WE("open_wallet", on_open_wallet, wallet_rpc::COMMAND_RPC_OPEN_WALLET) MAP_JON_RPC_WE("close_wallet", on_close_wallet, wallet_rpc::COMMAND_RPC_CLOSE_WALLET) MAP_JON_RPC_WE("change_wallet_password", on_change_wallet_password, wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD) - MAP_JON_RPC_WE("generate_from_view_key", on_generate_from_view_key, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS) MAP_JON_RPC_WE("generate_from_keys", on_generate_from_keys, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS) MAP_JON_RPC_WE("restore_deterministic_wallet", on_restore_deterministic_wallet, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET) MAP_JON_RPC_WE("is_multisig", on_is_multisig, wallet_rpc::COMMAND_RPC_IS_MULTISIG) @@ -218,7 +217,6 @@ namespace tools bool on_open_wallet(const wallet_rpc::COMMAND_RPC_OPEN_WALLET::request& req, wallet_rpc::COMMAND_RPC_OPEN_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_close_wallet(const wallet_rpc::COMMAND_RPC_CLOSE_WALLET::request& req, wallet_rpc::COMMAND_RPC_CLOSE_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_change_wallet_password(const wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD::request& req, wallet_rpc::COMMAND_RPC_CHANGE_WALLET_PASSWORD::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); - bool on_generate_from_view_key(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request& req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_generate_from_keys(const wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::request& req, wallet_rpc::COMMAND_RPC_GENERATE_FROM_KEYS::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_restore_deterministic_wallet(const wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::request& req, wallet_rpc::COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL); bool on_is_multisig(const wallet_rpc::COMMAND_RPC_IS_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_IS_MULTISIG::response& res, epee::json_rpc::error& er, const connection_context *ctx = NULL);