From f142c11ac634df487cc4bc65a5f1c9a3e3563dd9 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Thu, 21 Jul 2016 21:19:02 +0200 Subject: [PATCH] [0.13] Create a new HD seed after encrypting the wallet --- doc/release-notes.md | 2 ++ qa/rpc-tests/keypool.py | 10 ++++++++++ src/wallet/rpcwallet.cpp | 2 +- src/wallet/wallet.cpp | 9 +++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/doc/release-notes.md b/doc/release-notes.md index bb9118762..ad11fafd3 100644 --- a/doc/release-notes.md +++ b/doc/release-notes.md @@ -135,6 +135,8 @@ Existing wallets will still use traditional key generation. Backups of HD wallets, regardless of when they have been created, can therefore be used to re-generate all possible private keys, even the ones which haven't already been generated during the time of the backup. +**Attention:** Encrypting the wallet will create a new seed which requires +a new backup! HD key generation for new wallets can be disabled by `-usehd=0`. Keep in mind that this flag only has affect on newly created wallets. diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py index c75303ecb..735b91ee9 100755 --- a/qa/rpc-tests/keypool.py +++ b/qa/rpc-tests/keypool.py @@ -12,6 +12,11 @@ class KeyPoolTest(BitcoinTestFramework): def run_test(self): nodes = self.nodes + addr_before_encrypting = nodes[0].getnewaddress() + addr_before_encrypting_data = nodes[0].validateaddress(addr_before_encrypting) + wallet_info_old = nodes[0].getwalletinfo() + assert(addr_before_encrypting_data['hdmasterkeyid'] == wallet_info_old['masterkeyid']) + # Encrypt wallet and wait to terminate nodes[0].encryptwallet('test') bitcoind_processes[0].wait() @@ -19,6 +24,11 @@ class KeyPoolTest(BitcoinTestFramework): nodes[0] = start_node(0, self.options.tmpdir) # Keep creating keys addr = nodes[0].getnewaddress() + addr_data = nodes[0].validateaddress(addr) + wallet_info = nodes[0].getwalletinfo() + assert(addr_before_encrypting_data['hdmasterkeyid'] != wallet_info['masterkeyid']) + assert(addr_data['hdmasterkeyid'] == wallet_info['masterkeyid']) + try: addr = nodes[0].getnewaddress() raise AssertionError('Keypool should be exhausted after one address') diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 4087b8e77..a90807e51 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2081,7 +2081,7 @@ UniValue encryptwallet(const UniValue& params, bool fHelp) // slack space in .dat files; that is bad if the old data is // unencrypted private keys. So: StartShutdown(); - return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed, you need to make a new backup."; + return "wallet encrypted; Bitcoin server stopping, restart to run with encrypted wallet. The keypool has been flushed and a new HD seed was generated (if you are using HD). You need to make a new backup."; } UniValue lockunspent(const UniValue& params, bool fHelp) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 5908dfeac..a1d9c4a59 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -626,6 +626,15 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) Lock(); Unlock(strWalletPassphrase); + + // if we are using HD, replace the HD master key with a new one + if (!hdChain.masterKeyID.IsNull()) { + CKey key; + key.MakeNewKey(true); + if (!SetHDMasterKey(key)) + return false; + } + NewKeyPool(); Lock();