diff --git a/rai/core/core.cpp b/rai/core/core.cpp index 251f47dd5c..c629a67cd0 100644 --- a/rai/core/core.cpp +++ b/rai/core/core.cpp @@ -502,8 +502,7 @@ password (0, 1024) } else { - auto password_l (derive_key ("")); - password.value_set (password_l); + enter_password (""); } init_a = false; } @@ -1863,6 +1862,28 @@ void rai::rpc::operator () (boost::network::http::server ::request con response.content = "RPC control is disabled"; } } + else if (action == "password_valid") + { + boost::property_tree::ptree response_l; + response_l.put ("valid", client.wallet.valid_password () ? "1" : "0"); + set_response (response, response_l); + } + else if (action == "password_change") + { + boost::property_tree::ptree response_l; + std::string password_text (request_l.get ("password")); + auto error (client.wallet.rekey (password_text)); + response_l.put ("changed", error ? "0" : "1"); + set_response (response, response_l); + } + else if (action == "password_enter") + { + boost::property_tree::ptree response_l; + std::string password_text (request_l.get ("password")); + client.wallet.enter_password (password_text); + response_l.put ("valid", client.wallet.valid_password () ? "1" : "0"); + set_response (response, response_l); + } else { response = boost::network::http::server::response::stock_reply (boost::network::http::server::response::bad_request); @@ -4104,6 +4125,11 @@ bool rai::wallet::valid_password () return check () == check_l; } +void rai::wallet::enter_password (std::string const & password_a) +{ + password.value_set (derive_key (password_a)); +} + bool rai::transactions::rekey (std::string const & password_a) { std::lock_guard lock (mutex); diff --git a/rai/core/core.hpp b/rai/core/core.hpp index 6ed34a0037..4a3aeaed8e 100644 --- a/rai/core/core.hpp +++ b/rai/core/core.hpp @@ -294,13 +294,14 @@ namespace rai { wallet (bool &, boost::filesystem::path const &); rai::uint256_union check (); bool rekey (std::string const &); + bool valid_password (); + void enter_password (std::string const &); rai::uint256_union wallet_key (); rai::uint256_union salt (); void insert (rai::private_key const &); bool fetch (rai::public_key const &, rai::private_key &); bool exists (rai::public_key const &); bool generate_send (rai::ledger &, rai::public_key const &, rai::uint128_t const &, std::vector > &); - bool valid_password (); key_iterator find (rai::uint256_union const &); key_iterator begin (); key_iterator end (); diff --git a/rai/core_test/network.cpp b/rai/core_test/network.cpp index 3ba072ded1..2d77b407d5 100644 --- a/rai/core_test/network.cpp +++ b/rai/core_test/network.cpp @@ -726,6 +726,79 @@ TEST (rpc, wallet_add) ASSERT_EQ (account_text1, account_text2); } +TEST (rpc, wallet_password_valid) +{ + rai::system system (24000, 1); + auto pool (boost::make_shared ()); + rai::rpc rpc (system.service, pool, boost::asio::ip::address_v6::loopback (), 25000, *system.clients [0], true); + 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", "password_valid"); + 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); + std::string account_text1 (response_tree.get ("valid")); + ASSERT_EQ (account_text1, "1"); +} + +TEST (rpc, wallet_password_change) +{ + rai::system system (24000, 1); + auto pool (boost::make_shared ()); + rai::rpc rpc (system.service, pool, boost::asio::ip::address_v6::loopback (), 25000, *system.clients [0], true); + 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", "password_change"); + request_tree.put ("password", "test"); + 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); + std::string account_text1 (response_tree.get ("changed")); + ASSERT_EQ (account_text1, "1"); + ASSERT_TRUE (system.clients [0]->wallet.valid_password ()); + system.clients [0]->wallet.enter_password (""); + ASSERT_FALSE (system.clients [0]->wallet.valid_password ()); + system.clients [0]->wallet.enter_password ("test"); + ASSERT_TRUE (system.clients [0]->wallet.valid_password ()); +} + +TEST (rpc, wallet_password_enter) +{ + rai::system system (24000, 1); + auto pool (boost::make_shared ()); + rai::rpc rpc (system.service, pool, boost::asio::ip::address_v6::loopback (), 25000, *system.clients [0], true); + 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", "password_enter"); + request_tree.put ("password", ""); + 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); + std::string account_text1 (response_tree.get ("valid")); + ASSERT_EQ (account_text1, "1"); +} + TEST (network, receive_weight_change) { rai::system system (24000, 2); diff --git a/rai/core_test/wallet_test.cpp b/rai/core_test/wallet_test.cpp index 86e0e614aa..54e095f639 100644 --- a/rai/core_test/wallet_test.cpp +++ b/rai/core_test/wallet_test.cpp @@ -365,5 +365,9 @@ TEST (wallet, repoen_default_password) rai::wallet wallet (init, path); ASSERT_FALSE (init); ASSERT_TRUE (wallet.valid_password ()); + wallet.enter_password (" "); + ASSERT_FALSE (wallet.valid_password ()); + wallet.enter_password (""); + ASSERT_TRUE (wallet.valid_password ()); } } \ No newline at end of file diff --git a/rai/qt/qt.cpp b/rai/qt/qt.cpp index fd3fe15bef..f17991a1b4 100644 --- a/rai/qt/qt.cpp +++ b/rai/qt/qt.cpp @@ -36,7 +36,6 @@ send_blocks (new QPushButton ("Send")), wallet_add_account (new QPushButton ("Create account")), settings (new QPushButton ("Settings")), show_advanced (new QPushButton ("Advanced")), -wallet_refresh (new QPushButton ("Refresh")), send_blocks_window (new QWidget), send_blocks_layout (new QVBoxLayout), send_account_label (new QLabel ("Destination account:")), @@ -69,7 +68,6 @@ send_blocks_back (new QPushButton ("Back")) entry_window_layout->addWidget (wallet_add_account); entry_window_layout->addWidget (settings); entry_window_layout->addWidget (show_advanced); - entry_window_layout->addWidget (wallet_refresh); entry_window_layout->setContentsMargins (0, 0, 0, 0); entry_window_layout->setSpacing (5); entry_window->setLayout (entry_window_layout); @@ -137,10 +135,6 @@ send_blocks_back (new QPushButton ("Back")) settings_connect_line->setPalette (palette); } }); - QObject::connect (wallet_refresh, &QPushButton::released, [this] () - { - refresh_wallet (); - }); QObject::connect (settings_back, &QPushButton::released, [this] () { pop_main_stack (); @@ -232,6 +226,27 @@ send_blocks_back (new QPushButton ("Back")) client_m.wallet.insert (key.prv); refresh_wallet (); }); + client_m.send_observers.push_back ([this] (rai::send_block const &, rai::account const & account_a, rai::amount const &) + { + if (client_m.wallet.exists (account_a)) + { + refresh_wallet (); + } + }); + client_m.receive_observers.push_back ([this] (rai::receive_block const &, rai::account const & account_a, rai::amount const &) + { + if (client_m.wallet.exists (account_a)) + { + refresh_wallet (); + } + }); + client_m.open_observers.push_back ([this] (rai::open_block const &, rai::account const & account_a, rai::amount const &, rai::account const &) + { + if (client_m.wallet.exists (account_a)) + { + refresh_wallet (); + } + }); refresh_wallet (); } @@ -348,7 +363,7 @@ client (client_a) }); QObject::connect (unlock, &QPushButton::released, [this] () { - client.client_m.wallet.password.value_set (client.client_m.wallet.derive_key (std::string (password->text ().toLocal8Bit ()))); + client.client_m.wallet.enter_password (std::string (password->text ().toLocal8Bit ())); update_label (); }); QObject::connect (lock, &QPushButton::released, [this] () @@ -391,6 +406,7 @@ wallet_key_text (new QLabel ("Account key:")), wallet_key_line (new QLineEdit), wallet_add_key_button (new QPushButton ("Add account key")), search_for_receivables (new QPushButton ("Search for receivables")), +wallet_refresh (new QPushButton ("Refresh Wallet")), create_block (new QPushButton ("Create Block")), enter_block (new QPushButton ("Enter Block")), back (new QPushButton ("Back")), @@ -450,11 +466,17 @@ client (client_a) layout->addWidget (wallet_key_line); layout->addWidget (wallet_add_key_button); layout->addWidget (search_for_receivables); + layout->addWidget (wallet_refresh); layout->addWidget (create_block); layout->addWidget (enter_block); layout->addStretch (); layout->addWidget (back); window->setLayout (layout); + + QObject::connect (wallet_refresh, &QPushButton::released, [this] () + { + client.refresh_wallet (); + }); QObject::connect (show_log, &QPushButton::released, [this] () { client.push_main_stack (log_window); diff --git a/rai/qt/qt.hpp b/rai/qt/qt.hpp index fbc2754b23..6937e370db 100644 --- a/rai/qt/qt.hpp +++ b/rai/qt/qt.hpp @@ -52,6 +52,7 @@ namespace rai_qt { QLineEdit * wallet_key_line; QPushButton * wallet_add_key_button; QPushButton * search_for_receivables; + QPushButton * wallet_refresh; QPushButton * create_block; QPushButton * enter_block; QPushButton * back; @@ -170,7 +171,6 @@ namespace rai_qt { QPushButton * wallet_add_account; QPushButton * settings; QPushButton * show_advanced; - QPushButton * wallet_refresh; QWidget * send_blocks_window; QVBoxLayout * send_blocks_layout;