From de45c065f0648c4c41b57cb492420ceeed29dd11 Mon Sep 17 00:00:00 2001 From: Jonas Schnelli Date: Fri, 22 Jul 2016 11:03:30 +0200 Subject: [PATCH] [Wallet] Add CKeyMetadata record for HDMasterKey(s), factor out HD key generation --- qa/rpc-tests/keypool.py | 6 ++--- src/wallet/wallet.cpp | 49 ++++++++++++++++++++++++++++++----------- src/wallet/wallet.h | 5 ++++- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/qa/rpc-tests/keypool.py b/qa/rpc-tests/keypool.py index 735b91ee9..fa3947656 100755 --- a/qa/rpc-tests/keypool.py +++ b/qa/rpc-tests/keypool.py @@ -15,7 +15,7 @@ class KeyPoolTest(BitcoinTestFramework): 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']) + assert(addr_before_encrypting_data['hdmasterkeyid'] == wallet_info_old['hdmasterkeyid']) # Encrypt wallet and wait to terminate nodes[0].encryptwallet('test') @@ -26,8 +26,8 @@ class KeyPoolTest(BitcoinTestFramework): 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']) + assert(addr_before_encrypting_data['hdmasterkeyid'] != wallet_info['hdmasterkeyid']) + assert(addr_data['hdmasterkeyid'] == wallet_info['hdmasterkeyid']) try: addr = nodes[0].getnewaddress() diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index a1d9c4a59..e5ee5063a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -627,11 +627,11 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) Lock(); Unlock(strWalletPassphrase); - // if we are using HD, replace the HD master key with a new one + // if we are using HD, replace the HD master key (seed) with a new one if (!hdChain.masterKeyID.IsNull()) { CKey key; - key.MakeNewKey(true); - if (!SetHDMasterKey(key)) + CPubKey masterPubKey = GenerateNewHDMasterKey(); + if (!SetHDMasterKey(masterPubKey)) return false; } @@ -1175,20 +1175,43 @@ CAmount CWallet::GetChange(const CTransaction& tx) const return nChange; } -bool CWallet::SetHDMasterKey(const CKey& key) +CPubKey CWallet::GenerateNewHDMasterKey() +{ + CKey key; + key.MakeNewKey(true); + + int64_t nCreationTime = GetTime(); + CKeyMetadata metadata(nCreationTime); + + // calculate the pubkey + CPubKey pubkey = key.GetPubKey(); + assert(key.VerifyPubKey(pubkey)); + + // set the hd keypath to "m" -> Master, refers the masterkeyid to itself + metadata.hdKeypath = "m"; + metadata.hdMasterKeyID = pubkey.GetID(); + + { + LOCK(cs_wallet); + + // mem store the metadata + mapKeyMetadata[pubkey.GetID()] = metadata; + + // write the key&metadata to the database + if (!AddKeyPubKey(key, pubkey)) + throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed"); + } + + return pubkey; +} + +bool CWallet::SetHDMasterKey(const CPubKey& pubkey) { LOCK(cs_wallet); // ensure this wallet.dat can only be opened by clients supporting HD SetMinVersion(FEATURE_HD); - // store the key as normal "key"/"ckey" object - // in the database - // key metadata is not required - CPubKey pubkey = key.GetPubKey(); - if (!AddKeyPubKey(key, pubkey)) - throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed"); - // store the keyid (hash160) together with // the child index counter in the database // as a hdchain object @@ -3308,8 +3331,8 @@ bool CWallet::InitLoadWallet() if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && walletInstance->hdChain.masterKeyID.IsNull()) { // generate a new master key CKey key; - key.MakeNewKey(true); - if (!walletInstance->SetHDMasterKey(key)) + CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey(); + if (!walletInstance->SetHDMasterKey(masterPubKey)) throw std::runtime_error("CWallet::GenerateNewKey(): Storing master key failed"); } CPubKey newDefaultKey; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index efed2ba11..0c95fdf4b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -901,8 +901,11 @@ public: bool SetHDChain(const CHDChain& chain, bool memonly); const CHDChain& GetHDChain() { return hdChain; } + /* Generates a new HD master key (will not be activated) */ + CPubKey GenerateNewHDMasterKey(); + /* Set the current HD master key (will reset the chain child index counters) */ - bool SetHDMasterKey(const CKey& key); + bool SetHDMasterKey(const CPubKey& key); }; /** A key allocated from the key pool. */