mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-11-12 15:09:59 +01:00
Merge #13252: Wallet: Refactor ReserveKeyFromKeyPool for safety
4b62bdf513 Wallet: Refactor ReserveKeyFromKeyPool for safety (Ben Woosley)
Pull request description:
ReserveKeyFromKeyPool's previous behaviour is to set nIndex to -1 if the keypool is
empty, OR throw an exception for technical failures. Instead, we now return false
if the keypool is empty, true if the operation succeeded.
This is to make failure more easily detectable by calling code.
Tree-SHA512: 753f057ad13bd4c28d121f426bf0967ed72b827d97fb24582f9326ec60072abc5482e3db69ccada7c5fc66de9957fc59098432dd223fc4116991cab44c6d7aef
This commit is contained in:
@@ -3427,7 +3427,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
|
||||
return true;
|
||||
}
|
||||
|
||||
void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal)
|
||||
bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal)
|
||||
{
|
||||
nIndex = -1;
|
||||
keypool.vchPubKey = CPubKey();
|
||||
@@ -3438,11 +3438,13 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
|
||||
TopUpKeyPool();
|
||||
|
||||
bool fReturningInternal = IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT) && fRequestedInternal;
|
||||
std::set<int64_t>& setKeyPool = set_pre_split_keypool.empty() ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
|
||||
bool use_split_keypool = set_pre_split_keypool.empty();
|
||||
std::set<int64_t>& setKeyPool = use_split_keypool ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool;
|
||||
|
||||
// Get the oldest key
|
||||
if(setKeyPool.empty())
|
||||
return;
|
||||
if (setKeyPool.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WalletBatch batch(*database);
|
||||
|
||||
@@ -3456,14 +3458,17 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRe
|
||||
throw std::runtime_error(std::string(__func__) + ": unknown key in key pool");
|
||||
}
|
||||
// If the key was pre-split keypool, we don't care about what type it is
|
||||
if (set_pre_split_keypool.size() == 0 && keypool.fInternal != fReturningInternal) {
|
||||
if (use_split_keypool && keypool.fInternal != fReturningInternal) {
|
||||
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)
|
||||
@@ -3496,10 +3501,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;
|
||||
WalletBatch batch(*database);
|
||||
result = GenerateNewKey(batch, internal);
|
||||
@@ -3701,12 +3704,10 @@ bool CReserveKey::GetReservedKey(CPubKey& pubkey, bool internal)
|
||||
if (nIndex == -1)
|
||||
{
|
||||
CKeyPool keypool;
|
||||
pwallet->ReserveKeyFromKeyPool(nIndex, keypool, internal);
|
||||
if (nIndex != -1)
|
||||
vchPubKey = keypool.vchPubKey;
|
||||
else {
|
||||
if (!pwallet->ReserveKeyFromKeyPool(nIndex, keypool, internal)) {
|
||||
return false;
|
||||
}
|
||||
vchPubKey = keypool.vchPubKey;
|
||||
fInternal = keypool.fInternal;
|
||||
}
|
||||
assert(vchPubKey.IsValid());
|
||||
|
||||
Reference in New Issue
Block a user