| 3403 | } |
| 3404 | |
| 3405 | bool CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool fRequestedInternal) |
| 3406 | { |
| 3407 | nIndex = -1; |
| 3408 | keypool.vchPubKey = CPubKey(); |
| 3409 | { |
| 3410 | LOCK(cs_wallet); |
| 3411 | |
| 3412 | if (!IsLocked()) |
| 3413 | TopUpKeyPool(); |
| 3414 | |
| 3415 | bool fReturningInternal = IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT) && fRequestedInternal; |
| 3416 | bool use_split_keypool = set_pre_split_keypool.empty(); |
| 3417 | std::set<int64_t>& setKeyPool = use_split_keypool ? (fReturningInternal ? setInternalKeyPool : setExternalKeyPool) : set_pre_split_keypool; |
| 3418 | |
| 3419 | // Get the oldest key |
| 3420 | if (setKeyPool.empty()) { |
| 3421 | return false; |
| 3422 | } |
| 3423 | |
| 3424 | WalletBatch batch(*database); |
| 3425 | |
| 3426 | auto it = setKeyPool.begin(); |
| 3427 | nIndex = *it; |
| 3428 | setKeyPool.erase(it); |
| 3429 | if (!batch.ReadPool(nIndex, keypool)) { |
| 3430 | throw std::runtime_error(std::string(__func__) + ": read failed"); |
| 3431 | } |
| 3432 | if (!HaveKey(keypool.vchPubKey.GetID())) { |
| 3433 | throw std::runtime_error(std::string(__func__) + ": unknown key in key pool"); |
| 3434 | } |
| 3435 | // If the key was pre-split keypool, we don't care about what type it is |
| 3436 | if (use_split_keypool && keypool.fInternal != fReturningInternal) { |
| 3437 | throw std::runtime_error(std::string(__func__) + ": keypool entry misclassified"); |
| 3438 | } |
| 3439 | if (!keypool.vchPubKey.IsValid()) { |
| 3440 | throw std::runtime_error(std::string(__func__) + ": keypool entry invalid"); |
| 3441 | } |
| 3442 | |
| 3443 | m_pool_key_to_index.erase(keypool.vchPubKey.GetID()); |
| 3444 | WalletLogPrintf("keypool reserve %d\n", nIndex); |
| 3445 | } |
| 3446 | return true; |
| 3447 | } |
| 3448 | |
| 3449 | void CWallet::KeepKey(int64_t nIndex) |
| 3450 | { |