Skip to content

Conversation

@laanwj
Copy link
Member

@laanwj laanwj commented Jun 16, 2014

An user on IRC reported an issue where getrawchangeaddress keeps returning a single address when the keypool is exhausted. In my opinion this is unexpected behaviour.

In this commit:

  • Change CReserveKey to fail when running out of keys in the keypool.
  • Make getrawchangeaddress return RPC_WALLET_KEYPOOL_RAN_OUT when unable to create an address.
  • Add a Python RPC test for checking the keypool behaviour in combination with encrypted wallets.

The other uses of CReserveKey::GetReservedKey are:

  • In CWallet::CreateTransaction: right after unlocking the wallet, so no problem
  • In the internal miner in CreateNewBlockWithKey: the miner thread will exit when it cannot reserve a key. In This can happen with an encrypted wallet when the keypool is exhausted. As the internal miner is only used for testing, I think we can live with this.

Copy link
Member Author

Choose a reason for hiding this comment

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

BTW I was a bit surprised here; I do a keypoolrefill(3) with no keys left, but it needs to request four keys to exhaust the pool. Not sure yet why.

Copy link
Member

Choose a reason for hiding this comment

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

Perhaps some remaining artefact of a default key, requested before filling the keypool with N extra keys?

Copy link
Member Author

Choose a reason for hiding this comment

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

Right, that may be it - I want to debug this and know for sure before I merge this.

Regarding the 'default key', after this pull it is only used to detect whether this is the first run with a wallet. A later pull could remove it entirely.

Copy link
Member Author

Choose a reason for hiding this comment

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

OK, nothing sinister is going on here. One is added to the target size in TopUpKeypool. No idea why, but it's not harmful.

https://github.com/bitcoin/bitcoin/blob/master/src/wallet.cpp#L1765 :

        while (setKeyPool.size() < (nTargetSize + 1))

@laanwj laanwj added the Wallet label Jun 17, 2014
@laanwj laanwj changed the title getrawchangeaddress should fail when keypool exhausted getrawchangeaddress should fail when keypool exhausted + add tests Jun 18, 2014
@sipa
Copy link
Member

sipa commented Jun 21, 2014

Untested ACK

@jgarzik
Copy link
Contributor

jgarzik commented Jun 21, 2014

untested ACK

@gmaxwell
Copy link
Contributor

I have a little concern that people will write code which doesn't handle this rare failure and when it happens simply fail to take change entirely... but I don't have anything better to suggest.

@laanwj
Copy link
Member Author

laanwj commented Jun 22, 2014

@jgarzik The idea is that it should be possible to restart the mining thread with "setgenerate" after unlocking the wallet and generating a new keypool (still need to test this though). But requiring the entire process to shut down seems overly drastic.
Anyhow who would be 'actively mining' using the internal miner and an encrypted wallet? I mean, I suppose the internal miner is still useful for testnet-in-a-box, but that doesn't require top security.

@gmaxwell Well if you insist we can do it the careful way, make it an option then deprecate it over time. But if you don't take into account that RPC calls can fail that would be really strange, I doubt this is a very realistic concern.

@gmaxwell
Copy link
Contributor

@laanwj I doubt deprecating it would help— it's just the kind of sharp interface which may break people from time to time even if they're amply warned. I don't think we should do any different, I mentioned the concern only for the chance that someone would have some brillant idea I was missing.

@BitcoinPullTester
Copy link

Automatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/p4347_3b43f959e006ee880af60c3c0f33da9dd7d1ffc9/ for binaries and test log.
This test script verifies pulls every time they are updated. It, however, dies sometimes and fails to test properly. If you are waiting on a test, please check timestamps to verify that the test.log is moving at http://jenkins.bluematt.me/pull-tester/current/
Contact BlueMatt on freenode if something looks broken.

An user on IRC reported an issue where `getrawchangeaddress`
keeps returning a single address when the keypool is exhausted.
In my opinion this is strange behaviour.

- Change CReserveKey to fail when running out of keys in the keypool.
- Make `getrawchangeaddress` return RPC_WALLET_KEYPOOL_RAN_OUT when
  unable to create an address.
- Add a Python RPC test for checking the keypool behaviour in combination
  with encrypted wallets.
@laanwj laanwj merged commit 6c37f7f into bitcoin:master Jul 11, 2014
laanwj added a commit that referenced this pull request Jul 11, 2014
6c37f7f `getrawchangeaddress` should fail when keypool exhausted (Wladimir J. van der Laan)
@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.

5 participants