diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 15756ab74..e701a0ad9 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1121,10 +1121,20 @@ wallet_keys_unlocker::wallet_keys_unlocker(wallet2 &w, const epee::wipeable_stri w.generate_chacha_key_from_password(*password, key); boost::lock_guard lock(lockers_lock); - if (lockers_per_wallet[std::addressof(w)]++ > 0) + wallet2* w_ptr = std::addressof(w); + if (lockers_per_wallet[w_ptr]++ > 0) return; - w.decrypt_keys(key); + try + { + w.decrypt_keys(key); + } + catch (...) + { + if (--lockers_per_wallet[w_ptr] == 0) + lockers_per_wallet.erase(w_ptr); + throw; + } } wallet_keys_unlocker::~wallet_keys_unlocker() diff --git a/tests/unit_tests/wallet_storage.cpp b/tests/unit_tests/wallet_storage.cpp index 69c2f7664..6d256860a 100644 --- a/tests/unit_tests/wallet_storage.cpp +++ b/tests/unit_tests/wallet_storage.cpp @@ -595,3 +595,26 @@ TEST(wallet_keys_unlocker, first_not_locked) ASSERT_TRUE(verify_wallet_privkeys(w1)); } } + +TEST(wallet_keys_unlocker, construction_failure_rolls_back_lock_count) +{ + const epee::wipeable_string password("correct horse battery staple"); + const epee::wipeable_string wrong_password("correct horse battery stable"); + + tools::wallet2 w; + w.generate("", password); + ASSERT_TRUE(w.is_key_encryption_enabled()); + ASSERT_FALSE(w.is_unattended()); + ASSERT_FALSE(verify_wallet_privkeys(w)); + + ASSERT_ANY_THROW({ + tools::wallet_keys_unlocker ul(w, &wrong_password); + }); + ASSERT_FALSE(verify_wallet_privkeys(w)); + + { + tools::wallet_keys_unlocker ul(w, &password); + ASSERT_TRUE(verify_wallet_privkeys(w)); + } + ASSERT_FALSE(verify_wallet_privkeys(w)); +}