mirror of
https://github.com/monero-project/monero.git
synced 2024-12-26 20:49:27 -05:00
Merge pull request #4746
f3019efe
wallet-rpc: add on_restore_deterministic RPC call. (Hasan Pekdemir)
This commit is contained in:
commit
dd42b642ee
@ -3091,6 +3091,200 @@ namespace tools
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------------------------------------------------------
|
||||
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)
|
||||
{
|
||||
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.seed.empty())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "field 'seed' is mandatory. Please provide a seed you want to restore from.";
|
||||
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;
|
||||
}
|
||||
}
|
||||
crypto::secret_key recovery_key;
|
||||
std::string old_language;
|
||||
|
||||
// check the given seed
|
||||
{
|
||||
if (!crypto::ElectrumWords::words_to_bytes(req.seed, recovery_key, old_language))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "Electrum-style word list failed verification";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// process seed_offset if given
|
||||
{
|
||||
if (!req.seed_offset.empty())
|
||||
{
|
||||
recovery_key = cryptonote::decrypt_key(recovery_key, req.seed_offset);
|
||||
}
|
||||
}
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
epee::wipeable_string password = rc.second.password();
|
||||
|
||||
bool was_deprecated_wallet = ((old_language == crypto::ElectrumWords::old_language_name) ||
|
||||
crypto::ElectrumWords::get_is_old_style_seed(req.seed));
|
||||
|
||||
std::string mnemonic_language = old_language;
|
||||
if (was_deprecated_wallet)
|
||||
{
|
||||
// The user had used an older version of the wallet with old style mnemonics.
|
||||
res.was_deprecated = true;
|
||||
}
|
||||
|
||||
if (old_language == crypto::ElectrumWords::old_language_name)
|
||||
{
|
||||
if (req.language.empty())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "Wallet was using the old seed language. You need to specify a new seed language.";
|
||||
return false;
|
||||
}
|
||||
std::vector<std::string> language_list;
|
||||
std::vector<std::string> language_list_en;
|
||||
crypto::ElectrumWords::get_language_list(language_list);
|
||||
crypto::ElectrumWords::get_language_list(language_list_en, true);
|
||||
if (std::find(language_list.begin(), language_list.end(), req.language) == language_list.end() &&
|
||||
std::find(language_list_en.begin(), language_list_en.end(), req.language) == language_list_en.end())
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "Wallet was using the old seed language, and the specified new seed language is invalid.";
|
||||
return false;
|
||||
}
|
||||
mnemonic_language = req.language;
|
||||
}
|
||||
|
||||
wal->set_seed_language(mnemonic_language);
|
||||
|
||||
crypto::secret_key recovery_val;
|
||||
try
|
||||
{
|
||||
recovery_val = wal->generate(wallet_file, std::move(rc.second).password(), recovery_key, true, false, 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;
|
||||
}
|
||||
|
||||
// // Convert the secret key back to seed
|
||||
epee::wipeable_string electrum_words;
|
||||
if (!crypto::ElectrumWords::bytes_to_words(recovery_val, electrum_words, mnemonic_language))
|
||||
{
|
||||
er.code = WALLET_RPC_ERROR_CODE_UNKNOWN_ERROR;
|
||||
er.message = "Failed to encode seed";
|
||||
return false;
|
||||
}
|
||||
res.seed = electrum_words.data();
|
||||
|
||||
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_is_multisig(const wallet_rpc::COMMAND_RPC_IS_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_IS_MULTISIG::response& res, epee::json_rpc::error& er)
|
||||
{
|
||||
if (!m_wallet) return not_open(er);
|
||||
|
@ -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("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)
|
||||
MAP_JON_RPC_WE("make_multisig", on_make_multisig, wallet_rpc::COMMAND_RPC_MAKE_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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
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);
|
||||
bool on_make_multisig(const wallet_rpc::COMMAND_RPC_MAKE_MULTISIG::request& req, wallet_rpc::COMMAND_RPC_MAKE_MULTISIG::response& res, epee::json_rpc::error& er);
|
||||
|
@ -1931,6 +1931,43 @@ namespace wallet_rpc
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_RESTORE_DETERMINISTIC_WALLET
|
||||
{
|
||||
struct request
|
||||
{
|
||||
uint64_t restore_height;
|
||||
std::string filename;
|
||||
std::string seed;
|
||||
std::string seed_offset;
|
||||
std::string password;
|
||||
std::string language;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE_OPT(restore_height, (uint64_t)0)
|
||||
KV_SERIALIZE(filename)
|
||||
KV_SERIALIZE(seed)
|
||||
KV_SERIALIZE(seed_offset)
|
||||
KV_SERIALIZE(password)
|
||||
KV_SERIALIZE(language)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
|
||||
struct response
|
||||
{
|
||||
std::string address;
|
||||
std::string seed;
|
||||
std::string info;
|
||||
bool was_deprecated;
|
||||
|
||||
BEGIN_KV_SERIALIZE_MAP()
|
||||
KV_SERIALIZE(address)
|
||||
KV_SERIALIZE(seed)
|
||||
KV_SERIALIZE(info)
|
||||
KV_SERIALIZE(was_deprecated)
|
||||
END_KV_SERIALIZE_MAP()
|
||||
};
|
||||
};
|
||||
|
||||
struct COMMAND_RPC_IS_MULTISIG
|
||||
{
|
||||
struct request
|
||||
|
Loading…
Reference in New Issue
Block a user