diff --git a/rai/core/core.cpp b/rai/core/core.cpp index fd9931ed..14e24b89 100644 --- a/rai/core/core.cpp +++ b/rai/core/core.cpp @@ -871,6 +871,7 @@ bool rai::wallet::send (rai::account const & account_a, rai::uint128_t const & a bool rai::wallet::import (std::string const & json_a, std::string const & password_a) { + std::lock_guard lock (mutex); auto result (!store.valid_password ()); rai::wallet_store store_l (result, boost::filesystem::unique_path (), json_a); if (!result) @@ -950,6 +951,18 @@ std::shared_ptr rai::wallets::create (rai::uint256_union const & i return result; } +void rai::wallets::remove (rai::uint256_union const & id_a) +{ + auto existing (items.find (id_a)); + assert (existing != items.end ()); + auto wallet (existing->second); + items.erase (existing); + std::lock_guard lock (wallet->mutex); + wallet->store.handle.reset (); + assert (boost::filesystem::is_directory (path / id_a.to_string ())); + boost::filesystem::remove_all (path / id_a.to_string ()); +} + rai::key_iterator::key_iterator (leveldb::DB * db_a) : iterator (db_a->NewIterator (leveldb::ReadOptions ())) { @@ -2440,6 +2453,32 @@ void rai::rpc::operator () (boost::network::http::server ::request con response.content = "Bad account number"; } } + else if (action == "wallet_remove") + { + std::string wallet_text (request_l.get ("wallet")); + rai::uint256_union wallet; + auto error (wallet.decode_hex (wallet_text)); + if (!error) + { + auto existing (client.wallets.items.find (wallet)); + if (existing != client.wallets.items.end ()) + { + client.wallets.remove (wallet); + boost::property_tree::ptree response_l; + set_response (response, response_l); + } + else + { + response = boost::network::http::server::response::stock_reply (boost::network::http::server::response::bad_request); + response.content = "Wallet not found"; + } + } + else + { + response = boost::network::http::server::response::stock_reply (boost::network::http::server::response::bad_request); + response.content = "Bad account number"; + } + } else { response = boost::network::http::server::response::stock_reply (boost::network::http::server::response::bad_request); diff --git a/rai/core/core.hpp b/rai/core/core.hpp index 46ef15ff..73af3447 100644 --- a/rai/core/core.hpp +++ b/rai/core/core.hpp @@ -312,7 +312,6 @@ public: static size_t const kdf_full_work = 8 * 1024 * 1024; // 8 * 8 * 1024 * 1024 = 64 MB memory to derive key static size_t const kdf_test_work = 1024; static size_t const kdf_work = rai::rai_network == rai::rai_networks::rai_test_network ? kdf_test_work : kdf_full_work; -private: std::unique_ptr handle; }; class wallet @@ -333,6 +332,7 @@ public: wallets (rai::client &, boost::filesystem::path const &); std::shared_ptr open (rai::uint256_union const &); std::shared_ptr create (rai::uint256_union const &); + void remove (rai::uint256_union const &); std::unordered_map > items; boost::filesystem::path const path; rai::client & client; diff --git a/rai/core_test/rpc.cpp b/rai/core_test/rpc.cpp index 7db25a6a..9a1f0b65 100644 --- a/rai/core_test/rpc.cpp +++ b/rai/core_test/rpc.cpp @@ -635,4 +635,28 @@ TEST (rpc, wallet_export) rai::wallet_store store (error, boost::filesystem::unique_path (), wallet_json); ASSERT_FALSE (error); ASSERT_TRUE (store.exists (rai::test_genesis_key.pub)); +} + +TEST (rpc, wallet_remove) +{ + rai::system system (24000, 1); + auto wallet_id (system.clients [0]->wallets.items.begin ()->first); + auto pool (boost::make_shared ()); + rai::rpc rpc (system.service, pool, boost::asio::ip::address_v6::loopback (), 25000, *system.clients [0], true); + system.wallet (0)->store.insert (rai::test_genesis_key.prv); + boost::network::http::server ::request request; + boost::network::http::server ::response response; + request.method = "POST"; + boost::property_tree::ptree request_tree; + request_tree.put ("action", "wallet_remove"); + request_tree.put ("wallet", wallet_id.to_string ()); + std::stringstream ostream; + boost::property_tree::write_json (ostream, request_tree); + request.body = ostream.str (); + rpc (request, response); + ASSERT_EQ (boost::network::http::server ::response::ok, response.status); + boost::property_tree::ptree response_tree; + std::stringstream istream (response.content); + boost::property_tree::read_json (istream, response_tree); + ASSERT_EQ (system.clients [0]->wallets.items.end (), system.clients [0]->wallets.items.find (wallet_id)); } \ No newline at end of file diff --git a/rai/core_test/wallets.cpp b/rai/core_test/wallets.cpp index 944041e5..d486df23 100644 --- a/rai/core_test/wallets.cpp +++ b/rai/core_test/wallets.cpp @@ -29,4 +29,23 @@ TEST (wallets, open_existing) ASSERT_EQ (1, wallets.items.size ()); ASSERT_NE (nullptr, wallets.open (id)); } +} + +TEST (wallets, remove) +{ + rai::system system (24000, 1); + rai::uint256_union one (1); + auto path (boost::filesystem::unique_path ()); + { + rai::wallets wallets (*system.clients [0], path); + ASSERT_EQ (0, wallets.items.size ()); + auto wallet (wallets.create (one)); + ASSERT_EQ (1, wallets.items.size ()); + wallets.remove (one); + ASSERT_EQ (0, wallets.items.size ()); + } + { + rai::wallets wallets (*system.clients [0], path); + ASSERT_EQ (0, wallets.items.size ()); + } } \ No newline at end of file