1212#include < util/translation.h>
1313#include < wallet/scriptpubkeyman.h>
1414
15+ // ! Value for the first BIP 32 hardened derivation. Can be used as a bit mask and as a value. See BIP 32 for more details.
16+ const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000 ;
17+
1518bool LegacyScriptPubKeyMan::GetNewDestination (const OutputType type, CTxDestination& dest, std::string& error)
1619{
1720 LOCK (cs_KeyStore);
@@ -290,6 +293,43 @@ bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool i
290293 return true ;
291294}
292295
296+ bool LegacyScriptPubKeyMan::TopUpInactiveHDChain (const CKeyID seed_id, int64_t index, bool internal)
297+ {
298+ LOCK (cs_KeyStore);
299+
300+ if (m_storage.IsLocked ()) return false ;
301+
302+ auto it = m_inactive_hd_chains.find (seed_id);
303+ if (it == m_inactive_hd_chains.end ()) {
304+ return false ;
305+ }
306+
307+ CHDChain& chain = it->second ;
308+
309+ // Top up key pool
310+ int64_t target_size = std::max (gArgs .GetArg (" -keypool" , DEFAULT_KEYPOOL_SIZE), (int64_t ) 0 );
311+
312+ // "size" of the keypools. Not really the size, actually the difference between index and the chain counter
313+ // Since chain counter is 1 based and index is 0 based, one of them needs to be offset by 1.
314+ int64_t kp_size = (internal ? chain.nInternalChainCounter : chain.nExternalChainCounter ) - (index + 1 );
315+
316+ // make sure the keypool fits the user-selected target (-keypool)
317+ int64_t missing = std::max (std::max ((int64_t ) target_size, (int64_t ) 1 ) - kp_size, (int64_t ) 0 );
318+
319+ WalletBatch batch (m_storage.GetDatabase ());
320+ for (int64_t i = missing; i > 0 ; --i) {
321+ GenerateNewKey (batch, chain, internal);
322+ }
323+ if (missing > 0 ) {
324+ if (internal) {
325+ WalletLogPrintf (" inactive seed with id %s added %d internal keys\n " , HexStr (seed_id), missing);
326+ } else {
327+ WalletLogPrintf (" inactive seed with id %s added %d keys\n " , HexStr (seed_id), missing);
328+ }
329+ }
330+ return true ;
331+ }
332+
293333void LegacyScriptPubKeyMan::MarkUnusedAddresses (const CScript& script)
294334{
295335 LOCK (cs_KeyStore);
@@ -304,6 +344,19 @@ void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
304344 WalletLogPrintf (" %s: Topping up keypool failed (locked wallet)\n " , __func__);
305345 }
306346 }
347+
348+ auto it = mapKeyMetadata.find (keyid);
349+ if (it != mapKeyMetadata.end ()){
350+ CKeyMetadata meta = it->second ;
351+ if (!meta.hd_seed_id .IsNull () && meta.hd_seed_id != m_hd_chain.seed_id ) {
352+ bool internal = (meta.key_origin .path [1 ] & ~BIP32_HARDENED_KEY_LIMIT) != 0 ;
353+ int64_t index = meta.key_origin .path [2 ] & ~BIP32_HARDENED_KEY_LIMIT;
354+
355+ if (!TopUpInactiveHDChain (meta.hd_seed_id , index, internal)) {
356+ WalletLogPrintf (" %s: Adding inactive seed keys failed\n " , __func__);
357+ }
358+ }
359+ }
307360 }
308361}
309362
@@ -965,8 +1018,6 @@ CPubKey LegacyScriptPubKeyMan::GenerateNewKey(WalletBatch &batch, CHDChain& hd_c
9651018 return pubkey;
9661019}
9671020
968- const uint32_t BIP32_HARDENED_KEY_LIMIT = 0x80000000 ;
969-
9701021void LegacyScriptPubKeyMan::DeriveNewChildKey (WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, CHDChain& hd_chain, bool internal)
9711022{
9721023 // for now we use a fixed keypath scheme of m/0'/0'/k
0 commit comments