Skip to content

Conversation

@jonasschnelli
Copy link
Contributor

Reported by @dooglus.

Fixes #8383

Copy link
Member

Choose a reason for hiding this comment

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

Maybe the code should just check if HD is being used?

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 though about that but I think it's not worth adding another check here.

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 that's worth it either, just for the message

@luke-jr
Copy link
Member

luke-jr commented Jul 21, 2016

Will this destroy the old HD seed? Seems like it'd be valuable to keep it around somewhere...

@maflcko
Copy link
Member

maflcko commented Jul 21, 2016

@jonasschnelli Could you open this against master, please? (The backport can be done after merge and discussion/nits etc.)

@jonasschnelli
Copy link
Contributor Author

@luke-jr The old HD seed is still available over dumpwallet. You can get the CKeyID from the used masterkey when calling validateaddress.

Copy link
Member

Choose a reason for hiding this comment

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

Nit: please_use_lowercase_and_underscore

@jonasschnelli
Copy link
Contributor Author

Fixed the nits.
Sorry for opening this against 0.13 in the first place.

@maflcko
Copy link
Member

maflcko commented Jul 21, 2016

So this makes it impossible to encrypt a seed which is already in use and is planned to be used in the future, but I guess for 0.13 this is fair enough.

Concept ACK

Copy link
Contributor

Choose a reason for hiding this comment

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

SetHDMasterKey() can only return true. When it fails it throws an exception. Do we need to catch that exception?

Copy link
Member

Choose a reason for hiding this comment

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

Agree that it is confusing to have bool SomeFunction(), where the return value indicates if something bad happens but at the same time this is unused and exceptions are thrown. This should be made consistent.

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 think this solution is fine for the moment. The return value of SetHDMasterKey() is for future extensions and I think its useful even if its not possible to get a false returned with the current implementation.

The exception will already be caught though the RPC/Server logic (EncryptWallet() will only be called in the RPC context where we "handle" exceptions).

@pstratem
Copy link
Contributor

@jonasschnelli Does BDB guarantee the order in which keys are iterated? If not then this isn't guaranteed to work.

@pstratem
Copy link
Contributor

@jonasschnelli Indeed you're going to need to use the key metadata timestamp to select which hdchain to use.

@dooglus
Copy link
Contributor

dooglus commented Jul 22, 2016

@pstratem It reads to me as if the old hdchain key is overwritten by the new one:

bool CWalletDB::WriteHDChain(const CHDChain& chain)
{
    nWalletDBUpdated++;
    return Write(std::string("hdchain"), chain);
}

This WriteHDChain() function is used each time a new address is generated:

    // update the chain model in the database
    if (!CWalletDB(strWalletFile).WriteHDChain(hdChain))

The original chain could be stored under a different database key if we need to keep it around somewhere.

@pstratem
Copy link
Contributor

@dooglus indeed you're right... I'm not sure that is any better

certainly the old hd seed needs to be saved, possibly just with a prefix to make it not conflict or be used.

@jonasschnelli
Copy link
Contributor Author

jonasschnelli commented Jul 22, 2016

@pstratem: CWalletDB and BDB is a key value storage as far as I know. Writing the same key at later stage should replace the current value. It may be possible to have the old K/V still stored in the database, though, CWalletDB/BDB needs to make sure the later write operation will result in the laster read/mem-map operation during load wallet.

But I agree we need to keep track of the older/replaced seed. Maybe we should add something to the CKeyMetadata in that case (or at least CAddressBook).

@jonasschnelli
Copy link
Contributor Author

Pushed a commit that...

  1. ...factors out the creation of a new HD Master key (will be called now during init creation of the wallet as well as during encryption of the wallet)
  2. ...stores a CKeyMetadata record together with a HD master key where we set a hdkeypath="m" for later identifying this key as hd master key

https://github.com/bitcoin/bitcoin/pull/8206/files would make use of this. It would show old/rewritten master keys in the dumped wallet.

Copy link
Member

Choose a reason for hiding this comment

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

nit: argument is never used anywhere, but I could see this being useful in future

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 think this error detection case is extremely unlikely and probably on the same level then an exception during NewKeyPool().
I don't see a better way of handling this case.

@jonasschnelli
Copy link
Contributor Author

Fixed @instagibbs nits.

@pstratem
Copy link
Contributor

@jonasschnelli needs to be one commit

@laanwj
Copy link
Member

laanwj commented Jul 25, 2016

Is this only aimed at 0.13 on purpose?

@jonasschnelli
Copy link
Contributor Author

No. I should have opened this PR against master. I'll open a PR against master as soon as this one is "final" (maybe it cleanly applies to master).

@laanwj
Copy link
Member

laanwj commented Jul 27, 2016

Tested ACK 77c912d
Sorry, wrong issue - will test this one later

@instagibbs
Copy link
Member

utACK 77c912d

@jonasschnelli
Copy link
Contributor Author

Rebased (against 0.13).

@laanwj
Copy link
Member

laanwj commented Jul 28, 2016

code-review ACK de45c06, going to test

@laanwj
Copy link
Member

laanwj commented Jul 28, 2016

I did this:

$ rm ~/.bitcoin/regtest/wallet.dat
$ src/bitcoind -regtest -rpcport=1234 -daemon -usehd=1
Bitcoin server starting
$ src/bitcoin-cli  -regtest -rpcport=1234 dumpwallet "/tmp/dump_pre"
$ src/bitcoin-cli  -regtest -rpcport=1234 encryptwallet "pass"
wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup.
$ src/bitcoind -regtest -rpcport=1234 -daemon -usehd=1
Bitcoin server starting
$ src/bitcoin-cli  -regtest -rpcport=1234 walletpassphrase "pass" 12345
$ src/bitcoin-cli  -regtest -rpcport=1234 dumpwallet "/tmp/dump_post"
$ src/bitcoin-cli  -regtest -rpcport=1234 stop
$ diff  -du /tmp/dump_pre /tmp/dump_post

Result: http://www.hastebin.com/ajuhahofan.diff

Looks OK to me. The old reserve keys have been demoted to "change", and there are new reserve keys in the keypool. These keys are different, suggesting a new master key was used to generate them.

The old master key was kept around as "oldhdmaster":

-cSoMD7tEsoJNfSS3cL6N3E9gXpuQh7wgs79RDUBE6NjTEWS6Ptda 2016-07-28T10:48:28Z hdmaster=1 # addr=msqHNkZcD6ybT7xdCkquN4esLPLmoRyk8b hdkeypath=m
+cSoMD7tEsoJNfSS3cL6N3E9gXpuQh7wgs79RDUBE6NjTEWS6Ptda 2016-07-28T10:48:28Z inactivehdmaster=1 # addr=msqHNkZcD6ybT7xdCkquN4esLPLmoRyk8b hdkeypath=m

And a new one was added

+cRrbkixFuTz1esCbJTz3QqNGyEcPjFCjVyHRTy1JDxKDbHYXn9Qd 2016-07-28T10:48:43Z hdmaster=1 # addr=n3phnt6MDc2xUvKXrf8iW6ZiwtL2i7Rusm hdkeypath=m

The single key that is automatically generated (with empty label) at initialization stayed the same

 cRj4c74AFYdH9W1vbM3UgnaCeGbwztu3qb11NgDReiudtS2Q1ZAr 2016-07-28T10:48:28Z label= # addr=mwR8SR9sfKk7Q8z99xpdcCUNtccq81iRup hdkeypath=m/0'/0'/0'

For the new reserve keys it starts counting again at m/0'/0'/0'

+cNRrj6BtSxcXySqU6WgWgGEHMARifd1VXCVECdsXx4ervHE7iS4t 2016-07-28T10:48:43Z reserve=1 # addr=moBwgfzRf8H4ZjweCbQcckuJbMC16jwtD1 hdkeypath=m/0'/0'/0'

I think everything is as expected. Tested ACK.

@laanwj laanwj merged commit de45c06 into bitcoin:0.13 Jul 28, 2016
laanwj added a commit that referenced this pull request Jul 28, 2016
de45c06 [Wallet] Add CKeyMetadata record for HDMasterKey(s), factor out HD key generation (Jonas Schnelli)
f142c11 [0.13] Create a new HD seed after encrypting the wallet (Jonas Schnelli)
laanwj pushed a commit that referenced this pull request Jul 28, 2016
Forward-ports two commits from 0.13:
- [0.13] Create a new HD seed after encrypting the wallet
- [Wallet] Add CKeyMetadata record for HDMasterKey(s), factor out HD key generation

Github-Pull: #8389
Rebased-From: f142c11 de45c06
@maflcko
Copy link
Member

maflcko commented Jul 31, 2016

Removed "needs backport"


// if we are using HD, replace the HD master key (seed) with a new one
if (!hdChain.masterKeyID.IsNull()) {
CKey key;
Copy link
Contributor

Choose a reason for hiding this comment

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

Unused variable.

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.

7 participants