mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-02 09:46:52 -05:00
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).
This commit is contained in:
parent
70134eb34f
commit
8077862c5e
3 changed files with 69 additions and 56 deletions
|
@ -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);
|
||||
|
||||
// make sure the keypool fits the user-selected target (-keypool)
|
||||
int64_t missing = std::max(target_size - kp_size, (int64_t) 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
TopUpChain(chain, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1273,47 +1258,72 @@ bool LegacyScriptPubKeyMan::TopUp(unsigned int kpSize)
|
|||
if (!CanGenerateKeys()) {
|
||||
return false;
|
||||
}
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
|
||||
if (m_storage.IsLocked()) return false;
|
||||
|
||||
// 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);
|
||||
|
||||
// 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 (!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;
|
||||
}
|
||||
|
||||
CPubKey pubkey(GenerateNewKey(batch, m_hd_chain, internal));
|
||||
AddKeypoolPubkeyWithDB(pubkey, internal, batch);
|
||||
}
|
||||
if (missingInternal + missingExternal > 0) {
|
||||
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());
|
||||
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;
|
||||
}
|
||||
|
||||
bool LegacyScriptPubKeyMan::TopUpChain(CHDChain& chain, unsigned int kpSize)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
|
||||
if (m_storage.IsLocked()) return false;
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
CPubKey pubkey(GenerateNewKey(batch, chain, internal));
|
||||
if (chain == m_hd_chain) {
|
||||
AddKeypoolPubkeyWithDB(pubkey, internal, batch);
|
||||
}
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void LegacyScriptPubKeyMan::AddKeypoolPubkeyWithDB(const CPubKey& pubkey, const bool internal, WalletBatch& batch)
|
||||
{
|
||||
LOCK(cs_KeyStore);
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue