| 3345 | } |
| 3346 | |
| 3347 | bool CWallet::TopUpKeyPool(unsigned int kpSize) |
| 3348 | { |
| 3349 | if (IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) { |
| 3350 | return false; |
| 3351 | } |
| 3352 | { |
| 3353 | LOCK(cs_wallet); |
| 3354 | |
| 3355 | if (IsLocked()) |
| 3356 | return false; |
| 3357 | |
| 3358 | // Top up key pool |
| 3359 | unsigned int nTargetSize; |
| 3360 | if (kpSize > 0) |
| 3361 | nTargetSize = kpSize; |
| 3362 | else |
| 3363 | nTargetSize = std::max(gArgs.GetArg("-keypool", DEFAULT_KEYPOOL_SIZE), (int64_t) 0); |
| 3364 | |
| 3365 | // count amount of available keys (internal, external) |
| 3366 | // make sure the keypool of external and internal keys fits the user selected target (-keypool) |
| 3367 | int64_t missingExternal = std::max(std::max((int64_t) nTargetSize, (int64_t) 1) - (int64_t)setExternalKeyPool.size(), (int64_t) 0); |
| 3368 | int64_t missingInternal = std::max(std::max((int64_t) nTargetSize, (int64_t) 1) - (int64_t)setInternalKeyPool.size(), (int64_t) 0); |
| 3369 | |
| 3370 | if (!IsHDEnabled() || !CanSupportFeature(FEATURE_HD_SPLIT)) |
| 3371 | { |
| 3372 | // don't create extra internal keys |
| 3373 | missingInternal = 0; |
| 3374 | } |
| 3375 | bool internal = false; |
| 3376 | WalletBatch batch(*database); |
| 3377 | for (int64_t i = missingInternal + missingExternal; i--;) |
| 3378 | { |
| 3379 | if (i < missingInternal) { |
| 3380 | internal = true; |
| 3381 | } |
| 3382 | |
| 3383 | assert(m_max_keypool_index < std::numeric_limits<int64_t>::max()); // How in the hell did you use so many keys? |
| 3384 | int64_t index = ++m_max_keypool_index; |
| 3385 | |
| 3386 | CPubKey pubkey(GenerateNewKey(batch, internal)); |
| 3387 | if (!batch.WritePool(index, CKeyPool(pubkey, internal))) { |
| 3388 | throw std::runtime_error(std::string(__func__) + ": writing generated key failed"); |
| 3389 | } |
| 3390 | |
| 3391 | if (internal) { |
| 3392 | setInternalKeyPool.insert(index); |
| 3393 | } else { |
| 3394 | setExternalKeyPool.insert(index); |
| 3395 | } |
| 3396 | m_pool_key_to_index[pubkey.GetID()] = index; |
| 3397 | } |
| 3398 | if (missingInternal + missingExternal > 0) { |
| 3399 | 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()); |
| 3400 | } |
| 3401 | } |
| 3402 | return true; |
| 3403 | } |
| 3404 | |