diff options
Diffstat (limited to 'src/wallet/wallet2.cpp')
-rw-r--r-- | src/wallet/wallet2.cpp | 89 |
1 files changed, 84 insertions, 5 deletions
diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 8a868f3d8..6c271f037 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -48,6 +48,9 @@ using namespace epee; #include "cryptonote_protocol/blobdatatype.h" #include "mnemonics/electrum-words.h" #include "common/dns_utils.h" +#include "rapidjson/document.h" +#include "rapidjson/writer.h" +#include "rapidjson/stringbuffer.h" extern "C" { @@ -99,11 +102,19 @@ bool wallet2::get_seed(std::string& electrum_words) } /*! * \brief Sets the seed language + * \param language Seed language to set to */ void wallet2::set_seed_language(const std::string &language) { seed_language = language; } +/*! + * \brief Tells if the wallet file is deprecated. + */ +bool wallet2::is_deprecated() const +{ + return is_old_file_format; +} //---------------------------------------------------------------------------------------------------- void wallet2::process_new_transaction(const cryptonote::transaction& tx, uint64_t height) { @@ -432,7 +443,13 @@ bool wallet2::clear() m_local_bc_height = 1; return true; } -//---------------------------------------------------------------------------------------------------- + +/*! + * \brief Stores wallet information to wallet file. + * \param keys_file_name Name of wallet file + * \param password Password of wallet file + * \return Whether it was successful. + */ bool wallet2::store_keys(const std::string& keys_file_name, const std::string& password) { std::string account_data; @@ -440,6 +457,22 @@ bool wallet2::store_keys(const std::string& keys_file_name, const std::string& p CHECK_AND_ASSERT_MES(r, false, "failed to serialize wallet keys"); wallet2::keys_file_data keys_file_data = boost::value_initialized<wallet2::keys_file_data>(); + // Create a JSON object with "key_data" and "seed_language" as keys. + rapidjson::Document json; + json.SetObject(); + rapidjson::Value value(rapidjson::kStringType); + value.SetString(account_data.c_str(), account_data.length()); + json.AddMember("key_data", value, json.GetAllocator()); + value.SetString(seed_language.c_str(), seed_language.length()); + json.AddMember("seed_language", value, json.GetAllocator()); + + // Serialize the JSON object + rapidjson::StringBuffer buffer; + rapidjson::Writer<rapidjson::StringBuffer> writer(buffer); + json.Accept(writer); + account_data = buffer.GetString(); + + // Encrypt the entire JSON object. crypto::chacha8_key key; crypto::generate_chacha8_key(password, key); std::string cipher; @@ -465,30 +498,60 @@ namespace return r && expected_pub == pub; } } -//---------------------------------------------------------------------------------------------------- + +/*! + * \brief Load wallet information from wallet file. + * \param keys_file_name Name of wallet file + * \param password Password of wallet file + */ void wallet2::load_keys(const std::string& keys_file_name, const std::string& password) { wallet2::keys_file_data keys_file_data; std::string buf; bool r = epee::file_io_utils::load_file_to_string(keys_file_name, buf); THROW_WALLET_EXCEPTION_IF(!r, error::file_read_error, keys_file_name); + + // Decrypt the contents r = ::serialization::parse_binary(buf, keys_file_data); THROW_WALLET_EXCEPTION_IF(!r, error::wallet_internal_error, "internal error: failed to deserialize \"" + keys_file_name + '\"'); - crypto::chacha8_key key; crypto::generate_chacha8_key(password, key); std::string account_data; account_data.resize(keys_file_data.account_data.size()); crypto::chacha8(keys_file_data.account_data.data(), keys_file_data.account_data.size(), key, keys_file_data.iv, &account_data[0]); + // The contents should be JSON if the wallet follows the new format. + rapidjson::Document json; + if (json.Parse(account_data.c_str(), keys_file_data.account_data.size()).HasParseError()) + { + is_old_file_format = true; + } + else + { + account_data = std::string(json["key_data"].GetString(), json["key_data"].GetString() + + json["key_data"].GetStringLength()); + set_seed_language(std::string(json["seed_language"].GetString(), json["seed_language"].GetString() + + json["seed_language"].GetStringLength())); + } + const cryptonote::account_keys& keys = m_account.get_keys(); r = epee::serialization::load_t_from_binary(m_account, account_data); r = r && verify_keys(keys.m_view_secret_key, keys.m_account_address.m_view_public_key); r = r && verify_keys(keys.m_spend_secret_key, keys.m_account_address.m_spend_public_key); THROW_WALLET_EXCEPTION_IF(!r, error::invalid_password); } -//---------------------------------------------------------------------------------------------------- -crypto::secret_key wallet2::generate(const std::string& wallet_, const std::string& password, const crypto::secret_key& recovery_param, bool recover, bool two_random) + +/*! + * \brief Generates a wallet or restores one. + * \param wallet_ Name of wallet file + * \param password Password of wallet file + * \param recovery_param If it is a restore, the recovery key + * \param recover Whether it is a restore + * \param two_random Whether it is a non-deterministic wallet + * \return The secret key of the generated wallet + */ +crypto::secret_key wallet2::generate(const std::string& wallet_, const std::string& password, + const crypto::secret_key& recovery_param, bool recover, bool two_random) { clear(); prepare_file_names(wallet_); @@ -514,6 +577,22 @@ crypto::secret_key wallet2::generate(const std::string& wallet_, const std::stri store(); return retval; } + +/*! + * \brief Rewrites to the wallet file for wallet upgrade (doesn't generate key, assumes it's already there) + * \param wallet_name Name of wallet file (should exist) + * \param password Password for wallet file + */ +void wallet2::rewrite(const std::string& wallet_name, const std::string& password) +{ + prepare_file_names(wallet_name); + boost::system::error_code ignored_ec; + THROW_WALLET_EXCEPTION_IF(!boost::filesystem::exists(m_wallet_file, ignored_ec), error::file_not_found, m_wallet_file); + THROW_WALLET_EXCEPTION_IF(!boost::filesystem::exists(m_keys_file, ignored_ec), error::file_not_found, m_keys_file); + bool r = store_keys(m_keys_file, password); + THROW_WALLET_EXCEPTION_IF(!r, error::file_save_error, m_keys_file); + store(); +} //---------------------------------------------------------------------------------------------------- void wallet2::wallet_exists(const std::string& file_path, bool& keys_file_exists, bool& wallet_file_exists) { |