Skip to content

Conversation

@gmaxwell
Copy link
Contributor

@gmaxwell gmaxwell commented Jul 15, 2017

This carries the walletdb object from top-up through GenerateNewKey/DeriveNewChildKey/CWallet::AddKeyPubKey, which allows us to avoid the flush on destruction until the top up finishes instead of flushing the wallet for every key.

This speeds up adding keys by well over 10x on my laptop (actually something like 17x), I wouldn't be surprised if it were an even bigger speedup on spinning rust.

Then it increases the keypool size to 1000. I would have preferred to use 10,000 but in the case where the user creates a new wallet and then turns on encryption it seems kind of dumb to have >400KB of marked-used born unencrypted keys just laying around.

(Thanks to Matt for cluesticking me on how to bypass the crypter spaghetti)

@gmaxwell
Copy link
Contributor Author

@pstratem you might have some interest in reviewing this.

@laanwj laanwj added this to the 0.15.0 milestone Jul 15, 2017
@sipa
Copy link
Member

sipa commented Jul 15, 2017

utACK ff9a291b30d7464c1ff0990b1cab36d6119b2ae5

@instagibbs
Copy link
Member

tACK ff9a291

with 1000 keypool size, topup went from 20 seconds to 1.6.

@TheBlueMatt
Copy link
Contributor

utACK ff9a291b30d7464c1ff0990b1cab36d6119b2ae5 (needs rebase, though).

This is needed but not sufficient for batching the wallet flushing
 when topping up the keypool.
@gmaxwell
Copy link
Contributor Author

@TheBlueMatt rebased, please re-review

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems strange that we're creating a db transaction, only to throw it out in a second. I think its safe, but it might be nicer to let AddKeyPubKeyWithDB create a CWalletDB if it needs one automagically (eg by passing the walletdb in as a pointer).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't called when we don't need one; the case where we already have a dbwallet calls the WithDB version. (and changing the prototype of the function would mean changing the function it overrides, which a db handle doesn't even make sense for, and 29 callsites) Unless I'm misunderstanding you.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was confused, sorry.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another approach is to use dbw as the storage of the transaction. For instance, CWalletDBWrapper could keep a CBD instance, referenced counted by CWalletDB. This could be thread safe too.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm happy to write such alternative if there is interest.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seems like a reasonable thing to do, but I didn't even want to consider anything that complex-- I wanted to eliminate the complaint that having many keys is 'slow' for 0.15 because of the bad interactions with hd-wallet and rescan when the keypool isn't big.

@TheBlueMatt
Copy link
Contributor

TheBlueMatt commented Jul 17, 2017 via email

@promag
Copy link
Contributor

promag commented Jul 17, 2017

@TheBlueMatt another PR then.

utACK 3986271.

@sipa
Copy link
Member

sipa commented Jul 17, 2017

reutACK 3986271c0accfe896c66a48d3ed884a7553b6413

Copy link
Member

@laanwj laanwj Jul 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we increase the default keypool size, the LogPrintf("keypool added key %d message below shouldn't be logged for every key. Or at least moved to a debug category. It's ugly to log that many messages at first run, and it is performance overhead too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aggregated to a summary line.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unrelated, unless you want to fix all style issues?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we should nit people doing partial style issue fixes unless it affects reviewability.

Copy link
Member

@laanwj laanwj Jul 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this seems to be a "damned if you do, damned if you don't" thing.

  • If you deliberately make style fixes to code you touch, you get comments that it's unrelated
  • If you deliberately don't make style fixes to code you touch, you get questions why you didn't update the code for the style guidelines

I think both are valid, unless it makes review-ability in which case it could still be done in a separate commit in the same PR.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have been trying to limit them to things that will show up in the same patch hunks, and only changes which I'm pretty sure won't break review. I'm happy to do what other people want, though I prefer to at least fix braces (because I dislike reviewing the risky looking unbraced code myself)-- but ultimately I just need clear guidance to avoid the damned if/don't.

@instagibbs
Copy link
Member

reACK 4f81105

@jonasschnelli
Copy link
Contributor

Nice!
utACK 4f811059fab9a9121befae09f66b9b12244051f0.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this code.
Given that pwalletdbEncryption is not used in CCryptoKeyStore::AddKeyPubKey, could this code be moved before if (!CCryptoKeyStore::AddKeyPubKey? This would avoid some awkward duplication here.
Or is it used indirectly? This looks really sneaky. Please add a comment if you need to keep it at least, so that no one else gets my bad idea.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used-- alas, the whole purpose of that pre-existing terrible variable is because CCryptoKeyStore::AddKeyPubKey calls AddCryptedKey which on actual wallets is overridden to the function below. CCryptoKeyStore rightfully has no concept of wallet databases, so the variable is used to tunnel through it, to get it to the AddCryptedKey override below. This infrastructure was preexisting because the encryption setup needs it. I can add a comment explaining it. Some people have suggested larger refactors to remove this knitted maze, but it's clearly out of scope for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a comment

gmaxwell added 3 commits July 17, 2017 13:46
This prevents the wallet from being flushed between each and
 every key during top-up.  This results in a >10x speed-up
 for the top-up.
@gmaxwell
Copy link
Contributor Author

(new revisions are just due to adding a comment in the middle of the patch stack)

@laanwj laanwj merged commit b0e8e2d into bitcoin:master Jul 17, 2017
laanwj added a commit that referenced this pull request Jul 17, 2017
… and increase keypool size.

b0e8e2d Print one log message per keypool top-up, not one per key. (Gregory Maxwell)
41dc163 Increase wallet default keypool size to 1000. (Gregory Maxwell)
30d8f3a Pushdown walletdb though CWallet::AddKeyPubKey to avoid flushes. (Gregory Maxwell)
3a53f19 Pushdown walletdb object through GenerateNewKey/DeriveNewChildKey. (Gregory Maxwell)

Pull request description:

  This carries the walletdb object from top-up through GenerateNewKey/DeriveNewChildKey/CWallet::AddKeyPubKey, which allows us to avoid the flush on destruction until the top up finishes instead of flushing the wallet for every key.

  This speeds up adding keys by well over 10x on my laptop (actually something like 17x), I wouldn't be surprised if it were an even bigger speedup on spinning rust.

  Then it increases the keypool size to 1000. I would have preferred to use 10,000 but in the case where the user creates a new wallet and then turns on encryption it seems kind of dumb to have >400KB of marked-used born unencrypted keys just laying around.

  (Thanks to Matt for cluesticking me on how to bypass the crypter spaghetti)

Tree-SHA512: 868303de38fce4c3f67d7fe133f765f15435c94b39d252d7450b5fee5c607a3cc2f5e531861a69d8c8877bf130e0ff4c539f97500a6bc0ff6d67e4a42c9385c7
@TheBlueMatt
Copy link
Contributor

postumous utACK b0e8e2d (lets clean up some of this stuff in 16).

PastaPastaPasta added a commit to PastaPastaPasta/dash that referenced this pull request Aug 6, 2019
Signed-off-by: Pasta <pasta@dashboost.org>
UdjinM6 pushed a commit to dashpay/dash that referenced this pull request Aug 16, 2019
…ing top up and increase keypool size (#3045)

* backport bitcoin#10831

Signed-off-by: Pasta <pasta@dashboost.org>

* Apply the same logic for SetHDChain/SetCryptedHDChain
wqking added a commit to wqking-misc/Phore that referenced this pull request Jan 29, 2020
tohsnoom pushed a commit to phoreproject/Phore that referenced this pull request Jun 12, 2020
wqking added a commit to wqking-misc/SocialSend that referenced this pull request Aug 10, 2021
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants