Join GitHub today
GitHub is home to over 20 million developers working together to host and review code, manage projects, and build software together.
Track keypool entries as internal vs external in memory #10235
Conversation
TheBlueMatt
referenced
this pull request
Apr 19, 2017
Closed
[Wallet] Worst case performance improvement on KeyPool filtering #10184
|
Concept ACK. |
jonasschnelli
added Refactoring Wallet
labels
Apr 19, 2017
| @@ -2975,25 +2985,8 @@ bool CWallet::NewKeyPool() | ||
| size_t CWallet::KeypoolCountExternalKeys() |
|
I really like this PR. This is simpler than before, utACK. You should remove |
|
@jonasschnelli the line count is almost the same. But it was better to not break the reviews, this was already a big PR. |
jonasschnelli
referenced
this pull request
May 4, 2017
Closed
Add HD wallet auto-restore functionality #10240
ryanofsky
reviewed
May 5, 2017
(These review comments are actually from Tuesday. Apparently I forgot to press the submit button.)
| @@ -3051,30 +3048,29 @@ void CWallet::ReserveKeyFromKeyPool(int64_t& nIndex, CKeyPool& keypool, bool int | ||
| if (!IsLocked()) | ||
| TopUpKeyPool(); | ||
| + bool fInternal = IsHDEnabled() && CanSupportFeature(FEATURE_HD_SPLIT) && internal; |
ryanofsky
May 5, 2017
Contributor
Having both internal and fInternal variables in the same scope with slightly different meanings seems error prone. Consider renaming one or both. I might go with requestedInternal and actuallyInternal.
| - return; | ||
| - } | ||
| + nIndex = *setKeyPool.begin(); | ||
| + setKeyPool.erase(nIndex); |
| @@ -3118,46 +3118,34 @@ bool CWallet::GetKeyFromPool(CPubKey& result, bool internal) | ||
| return true; | ||
| } | ||
| +static int64_t GetOldestKeyInPool(const std::set<int64_t>& setKeyPool, CWalletDB& walletdb) { | ||
| + CKeyPool keypool; | ||
| + int64_t nIndex = *(setKeyPool.begin()); |
| + oldestKey = std::max(GetOldestKeyInPool(setInternalKeyPool, walletdb), oldestKey); | ||
| + } | ||
| + if (!setExternalKeyPool.empty()) { | ||
| + oldestKey = std::max(GetOldestKeyInPool(setExternalKeyPool, walletdb), oldestKey); |
ryanofsky
May 5, 2017
Contributor
This new code doesn't seem equivalent to the old code. Previously, if HD_SPLIT were true but there were 0 internal keys, it would return current timestamp now. Now it will return oldest external key time. Also vice versa (swapping internal/external).
|
Addressed @ryanofsky's comments and rebased. |
ryanofsky
reviewed
May 10, 2017
utACK f4390a7. Changes since previous review: rebase, fInternal variable renames, iterator erase call, GetOldestKeyPoolTime bugfix.
| - | ||
| - // if the keypool is empty, return <NOW> | ||
| - if (setKeyPool.empty()) | ||
| +static int64_t GetOldestKeyInPool(const std::set<int64_t>& setKeyPool, CWalletDB& walletdb) { |
ryanofsky
May 10, 2017
Contributor
In commit "Track keypool entries as internal vs external in memory"
The previous name GetOldestKeyPoolTime might be better name for this since it is returning a time.
| + LOCK(cs_wallet); | ||
| + | ||
| + CWalletDB walletdb(*dbw); | ||
| + int64_t oldestKey = -1; |
ryanofsky
May 10, 2017
Contributor
In commit "Track keypool entries as internal vs external in memory"
You could initialize this to GetOldest(external) to save a line of code and get rid of the -1 magic value.
|
@jonasschnelli, do you want to review this? It seems like it simplifies some things and could interact nicely with #10240 and #10238. |
| @@ -2993,8 +2986,8 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize) | ||
| // count amount of available keys (internal, external) | ||
| // make sure the keypool of external and internal keys fits the user selected target (-keypool) | ||
| - int64_t amountExternal = KeypoolCountExternalKeys(); | ||
| - int64_t amountInternal = setKeyPool.size() - amountExternal; | ||
| + int64_t amountExternal = setExternalKeyPool.size(); |
jonasschnelli
Jun 8, 2017
Member
nit: amountExternal is not longer required, setExternalKeyPool.size() can be used directly at L2991+.
| - } | ||
| + auto it = setKeyPool.begin(); | ||
| + nIndex = *it; | ||
| + setKeyPool.erase(it); |
jonasschnelli
Jun 8, 2017
Member
Ideally setKeyPool.erase() happens after the DB read and HaveKey/fInternal check? No?
TheBlueMatt
Jun 21, 2017
Contributor
If there are any issues with that key, best to get it out of the pool so that future calls succeed (though, really, those should be fatal StartShutdown() issues, not just runtime_errors that the RPC interface will return).
|
Reviewed. |
|
Rebased and addressed all the comments, I believe. |
|
utACK 435c272 |
|
Would be nice to get this for 15 to avoid some minor performance regressions. |
This seems like it could be merged now. I don't see anything that would hold it up. |
| + nEnd = *(--setInternalKeyPool.end()) + 1; | ||
| + } | ||
| + if (!setExternalKeyPool.empty()) { | ||
| + nEnd = std::max(nEnd, *(--setExternalKeyPool.end()) + 1); |
TheBlueMatt
referenced
this pull request
Jul 11, 2017
Merged
No longer ever reuse keypool indexes #10795
ryanofsky
reviewed
Jul 11, 2017
utACK 1ee8c0f, but IMO the new commit makes the code worse. Before you could clearly see what TopUpKeyPool was doing if either of the sets were empty. Now you have to look inside the definition of a dodgy GetHighestSetElement function in another part of the code to find out what it returns when a set is empty and what implications that has for the max value. Would be better to drop this commit and just replace *--end() with *rbegin() in the original code, I think.
Only change since last review is the new commit.
| @@ -3106,6 +3106,12 @@ size_t CWallet::KeypoolCountExternalKeys() | ||
| return setExternalKeyPool.size(); | ||
| } | ||
| +// Get highest element in a uint64_t set (eg keypools), or 0 if its empty |
|
@ryanofsky OK, I restored it closer to where it was. That code goes away in #10795 anyway. |
| + } else { | ||
| + setExternalKeyPool.insert(nEnd); | ||
| + } | ||
| + LogPrintf("keypool added key %d, size=%u, internal=%d\n", nEnd, setInternalKeyPool.size() + setExternalKeyPool.size(), internal); |
morcos
Jul 12, 2017
Contributor
nit: print external and internal sizes or only size for keypool you're adding to
|
utACK bdf6ba8. I started reviewing the first commit, made two review comments, and your two further commits exactly fixed those issues :) |
TheBlueMatt
added some commits
Apr 19, 2017
|
utACK d40a72c, only change is the keypool size logging. |
|
utACK d40a72c |
sipa
merged commit d40a72c
into
bitcoin:master
Jul 15, 2017
1 check passed
sipa
added a commit
that referenced
this pull request
Jul 15, 2017
|
|
sipa |
5cfdda2
|
laanwj
added a commit
that referenced
this pull request
Jul 18, 2017
|
|
laanwj |
7b6e8bc
|
|
Post merge ACK |
TheBlueMatt commentedApr 19, 2017
This is an alternative version of #10184. As @jonasschnelli points out there, the performance regressions are pretty minimal, but given that this is a pretty simple, mechanical change, its probably worth doing.