diff options
author | Andrew Chow <achow101-github@achow101.com> | 2021-10-18 15:27:27 -0400 |
---|---|---|
committer | Andrew Chow <achow101-github@achow101.com> | 2022-01-14 15:03:15 -0500 |
commit | 8077862c5e8a3ed501f0baabc33536eb16922ceb (patch) | |
tree | 5affda338dde813a50971d6ad31b67d5766c6c24 | |
parent | 70134eb34f58f0c572e7c3775e292d408f03b5ab (diff) | |
download | bitcoin-8077862c5e8a3ed501f0baabc33536eb16922ceb.tar.xz |
wallet: Refactor TopUp to be able to top up inactive chains too
Refactors TopUp so that it also tops up inactive chains. The bulk of
TopUp is moved to TopUpChain.
CHDChain also has 2 new in memory variables to track its highest used
indexes. This is used only for inactive hd chains so that they can be
topped up later in the same session (e.g. if the wallet is encrypted and
not unlocked at the time of MarkUnusedAddresses).
-rw-r--r-- | src/wallet/scriptpubkeyman.cpp | 106 | ||||
-rw-r--r-- | src/wallet/scriptpubkeyman.h | 1 | ||||
-rw-r--r-- | src/wallet/walletdb.h | 2 |
3 files changed, 61 insertions, 48 deletions
diff --git a/src/wallet/scriptpubkeyman.cpp b/src/wallet/scriptpubkeyman.cpp index 7cca5fba20..507951134b 100644 --- a/src/wallet/scriptpubkeyman.cpp +++ b/src/wallet/scriptpubkeyman.cpp @@ -321,8 +321,6 @@ bool LegacyScriptPubKeyMan::TopUpInactiveHDChain(const CKeyID seed_id, int64_t i { LOCK(cs_KeyStore); - if (m_storage.IsLocked()) return false; - auto it = m_inactive_hd_chains.find(seed_id); if (it == m_inactive_hd_chains.end()) { return false; @@ -330,27 +328,14 @@ bool LegacyScriptPubKeyMan::TopUpInactiveHDChain(const CKeyID seed_id, int64_t i CHDChain& chain = it->second; - // Top up key pool - int64_t target_size = std::max(gArgs.GetIntArg("-keypool", DEFAULT_KEYPOOL_SIZE), (int64_t) 1); - - // "size" of the keypools. Not really the size, actually the difference between index and the chain counter - // Since chain counter is 1 based and index is 0 based, one of them needs to be offset by 1. - int64_t kp_size = (internal ? chain.nInternalChainCounter : chain.nExternalChainCounter) - (index + 1); + if (internal) { + chain.m_next_internal_index = std::max(chain.m_next_internal_index, index + 1); + } else { + chain.m_next_external_index = std::max(chain.m_next_external_index, index + 1); + } - // make sure the keypool fits the user-selected target (-keypool) - int64_t missing = std::max(target_size - kp_size, (int64_t) 0); + TopUpChain(chain, 0); - if (missing > 0) { - WalletBatch batch(m_storage.GetDatabase()); - for (int64_t i = missing; i > 0; --i) { - GenerateNewKey(batch, chain, internal); - } - if (internal) { - WalletLogPrintf("inactive seed with id %s added %d internal keys\n", HexStr(seed_id), missing); - } else { - WalletLogPrintf("inactive seed with id %s added %d keys\n", HexStr(seed_id), missing); - } - } return true; } @@ -1273,44 +1258,69 @@ bool LegacyScriptPubKeyMan::TopUp(unsigned int kpSize) if (!CanGenerateKeys()) { return false; } - { - LOCK(cs_KeyStore); - if (m_storage.IsLocked()) return false; + if (!TopUpChain(m_hd_chain, kpSize)) { + return false; + } + for (auto& [chain_id, chain] : m_inactive_hd_chains) { + if (!TopUpChain(chain, kpSize)) { + return false; + } + } + NotifyCanGetAddressesChanged(); + return true; +} - // Top up key pool - unsigned int nTargetSize; - if (kpSize > 0) - nTargetSize = kpSize; - else - nTargetSize = std::max(gArgs.GetIntArg("-keypool", DEFAULT_KEYPOOL_SIZE), (int64_t) 0); +bool LegacyScriptPubKeyMan::TopUpChain(CHDChain& chain, unsigned int kpSize) +{ + LOCK(cs_KeyStore); - // count amount of available keys (internal, external) - // make sure the keypool of external and internal keys fits the user selected target (-keypool) - int64_t missingExternal = std::max(std::max((int64_t) nTargetSize, (int64_t) 1) - (int64_t)setExternalKeyPool.size(), (int64_t) 0); - int64_t missingInternal = std::max(std::max((int64_t) nTargetSize, (int64_t) 1) - (int64_t)setInternalKeyPool.size(), (int64_t) 0); + if (m_storage.IsLocked()) return false; - if (!IsHDEnabled() || !m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) - { - // don't create extra internal keys - missingInternal = 0; + // Top up key pool + unsigned int nTargetSize; + if (kpSize > 0) { + nTargetSize = kpSize; + } else { + nTargetSize = std::max(gArgs.GetIntArg("-keypool", DEFAULT_KEYPOOL_SIZE), int64_t{0}); + } + int64_t target = std::max((int64_t) nTargetSize, int64_t{1}); + + // count amount of available keys (internal, external) + // make sure the keypool of external and internal keys fits the user selected target (-keypool) + int64_t missingExternal; + int64_t missingInternal; + if (chain == m_hd_chain) { + missingExternal = std::max(target - (int64_t)setExternalKeyPool.size(), int64_t{0}); + missingInternal = std::max(target - (int64_t)setInternalKeyPool.size(), int64_t{0}); + } else { + missingExternal = std::max(target - (chain.nExternalChainCounter - chain.m_next_external_index), int64_t{0}); + missingInternal = std::max(target - (chain.nInternalChainCounter - chain.m_next_internal_index), int64_t{0}); + } + + if (!IsHDEnabled() || !m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) { + // don't create extra internal keys + missingInternal = 0; + } + bool internal = false; + WalletBatch batch(m_storage.GetDatabase()); + for (int64_t i = missingInternal + missingExternal; i--;) { + if (i < missingInternal) { + internal = true; } - bool internal = false; - WalletBatch batch(m_storage.GetDatabase()); - for (int64_t i = missingInternal + missingExternal; i--;) - { - if (i < missingInternal) { - internal = true; - } - CPubKey pubkey(GenerateNewKey(batch, m_hd_chain, internal)); + CPubKey pubkey(GenerateNewKey(batch, chain, internal)); + if (chain == m_hd_chain) { AddKeypoolPubkeyWithDB(pubkey, internal, batch); } - if (missingInternal + missingExternal > 0) { + } + if (missingInternal + missingExternal > 0) { + if (chain == m_hd_chain) { WalletLogPrintf("keypool added %d keys (%d internal), size=%u (%u internal)\n", missingInternal + missingExternal, missingInternal, setInternalKeyPool.size() + setExternalKeyPool.size() + set_pre_split_keypool.size(), setInternalKeyPool.size()); + } else { + WalletLogPrintf("inactive seed with id %s added %d external keys, %d internal keys\n", HexStr(chain.seed_id), missingExternal, missingInternal); } } - NotifyCanGetAddressesChanged(); return true; } diff --git a/src/wallet/scriptpubkeyman.h b/src/wallet/scriptpubkeyman.h index ebe064fa0a..e97f0bb40c 100644 --- a/src/wallet/scriptpubkeyman.h +++ b/src/wallet/scriptpubkeyman.h @@ -354,6 +354,7 @@ private: */ bool TopUpInactiveHDChain(const CKeyID seed_id, int64_t index, bool internal); + bool TopUpChain(CHDChain& chain, unsigned int size); public: using ScriptPubKeyMan::ScriptPubKeyMan; diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 9c752623b3..428f3d36ec 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -90,6 +90,8 @@ public: uint32_t nExternalChainCounter; uint32_t nInternalChainCounter; CKeyID seed_id; //!< seed hash160 + int64_t m_next_external_index{0}; // Next index in the keypool to be used. Memory only. + int64_t m_next_internal_index{0}; // Next index in the keypool to be used. Memory only. static const int VERSION_HD_BASE = 1; static const int VERSION_HD_CHAIN_SPLIT = 2; |