diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1099,7 +1099,22 @@ bool NewKeyPool(); size_t KeypoolCountExternalKeys() EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); bool TopUpKeyPool(unsigned int kpSize = 0); - void ReserveKeyFromKeyPool(int64_t &nIndex, CKeyPool &keypool, + + /** + * Reserves a key from the keypool and sets nIndex to its index + * + * @param[out] nIndex the index of the key in keypool + * @param[out] keypool the keypool the key was drawn from, which could be + * the the pre-split pool if present, or the internal or external pool + * @param fRequestedInternal true if the caller would like the key drawn + * from the internal keypool, false if external is preferred + * + * @return true if succeeded, false if failed due to empty keypool + * @throws std::runtime_error if keypool read failed, key was invalid, + * was not found in the wallet, or was misclassified in the internal + * or external keypool + */ + bool ReserveKeyFromKeyPool(int64_t &nIndex, CKeyPool &keypool, bool fRequestedInternal); void KeepKey(int64_t nIndex); void ReturnKey(int64_t nIndex, bool fInternal, const CPubKey &pubkey); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -3668,7 +3668,7 @@ return true; } -void CWallet::ReserveKeyFromKeyPool(int64_t &nIndex, CKeyPool &keypool, +bool CWallet::ReserveKeyFromKeyPool(int64_t &nIndex, CKeyPool &keypool, bool fRequestedInternal) { nIndex = -1; keypool.vchPubKey = CPubKey(); @@ -3687,7 +3687,7 @@ // Get the oldest key if (setKeyPool.empty()) { - return; + return false; } WalletBatch batch(*database); @@ -3706,10 +3706,15 @@ throw std::runtime_error(std::string(__func__) + ": keypool entry misclassified"); } + if (!keypool.vchPubKey.IsValid()) { + throw std::runtime_error(std::string(__func__) + + ": keypool entry invalid"); + } - assert(keypool.vchPubKey.IsValid()); m_pool_key_to_index.erase(keypool.vchPubKey.GetID()); LogPrintf("keypool reserve %d\n", nIndex); + + return true; } void CWallet::KeepKey(int64_t nIndex) { @@ -3737,9 +3742,8 @@ bool CWallet::GetKeyFromPool(CPubKey &result, bool internal) { CKeyPool keypool; LOCK(cs_wallet); - int64_t nIndex = 0; - ReserveKeyFromKeyPool(nIndex, keypool, internal); - if (nIndex == -1) { + int64_t nIndex; + if (!ReserveKeyFromKeyPool(nIndex, keypool, internal)) { if (IsLocked()) { return false; } @@ -3954,8 +3958,7 @@ bool CReserveKey::GetReservedKey(CPubKey &pubkey, bool internal) { if (nIndex == -1) { CKeyPool keypool; - pwallet->ReserveKeyFromKeyPool(nIndex, keypool, internal); - if (nIndex == -1) { + if (!pwallet->ReserveKeyFromKeyPool(nIndex, keypool, internal)) { return false; }