Add generate_from_keys RPC method

This commit is contained in:
Joel 2019-02-19 14:13:01 +01:00
parent 31bdf7bd11
commit 7dd7a3b791
3 changed files with 201 additions and 0 deletions

View file

@ -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<std::string, true> 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<wallet2> 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())