Browse Source

[Wallet] Add CKeyMetadata record for HDMasterKey(s), factor out HD key generation

0.13
Jonas Schnelli 8 years ago
parent
commit
de45c065f0
No known key found for this signature in database
GPG Key ID: 29D4BCB6416F53EC
  1. 6
      qa/rpc-tests/keypool.py
  2. 47
      src/wallet/wallet.cpp
  3. 5
      src/wallet/wallet.h

6
qa/rpc-tests/keypool.py

@ -15,7 +15,7 @@ class KeyPoolTest(BitcoinTestFramework):
addr_before_encrypting = nodes[0].getnewaddress() addr_before_encrypting = nodes[0].getnewaddress()
addr_before_encrypting_data = nodes[0].validateaddress(addr_before_encrypting) addr_before_encrypting_data = nodes[0].validateaddress(addr_before_encrypting)
wallet_info_old = nodes[0].getwalletinfo() 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 # Encrypt wallet and wait to terminate
nodes[0].encryptwallet('test') nodes[0].encryptwallet('test')
@ -26,8 +26,8 @@ class KeyPoolTest(BitcoinTestFramework):
addr = nodes[0].getnewaddress() addr = nodes[0].getnewaddress()
addr_data = nodes[0].validateaddress(addr) addr_data = nodes[0].validateaddress(addr)
wallet_info = nodes[0].getwalletinfo() wallet_info = nodes[0].getwalletinfo()
assert(addr_before_encrypting_data['hdmasterkeyid'] != wallet_info['masterkeyid']) assert(addr_before_encrypting_data['hdmasterkeyid'] != wallet_info['hdmasterkeyid'])
assert(addr_data['hdmasterkeyid'] == wallet_info['masterkeyid']) assert(addr_data['hdmasterkeyid'] == wallet_info['hdmasterkeyid'])
try: try:
addr = nodes[0].getnewaddress() addr = nodes[0].getnewaddress()

47
src/wallet/wallet.cpp

@ -627,11 +627,11 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
Lock(); Lock();
Unlock(strWalletPassphrase); 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()) { if (!hdChain.masterKeyID.IsNull()) {
CKey key; CKey key;
key.MakeNewKey(true); CPubKey masterPubKey = GenerateNewHDMasterKey();
if (!SetHDMasterKey(key)) if (!SetHDMasterKey(masterPubKey))
return false; return false;
} }
@ -1175,19 +1175,42 @@ CAmount CWallet::GetChange(const CTransaction& tx) const
return nChange; return nChange;
} }
bool CWallet::SetHDMasterKey(const CKey& key) CPubKey CWallet::GenerateNewHDMasterKey()
{ {
LOCK(cs_wallet); CKey key;
key.MakeNewKey(true);
// ensure this wallet.dat can only be opened by clients supporting HD int64_t nCreationTime = GetTime();
SetMinVersion(FEATURE_HD); CKeyMetadata metadata(nCreationTime);
// store the key as normal "key"/"ckey" object // calculate the pubkey
// in the database
// key metadata is not required
CPubKey pubkey = key.GetPubKey(); 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)) if (!AddKeyPubKey(key, pubkey))
throw std::runtime_error("CWallet::GenerateNewKey(): AddKey failed"); 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 keyid (hash160) together with // store the keyid (hash160) together with
// the child index counter in the database // the child index counter in the database
@ -3308,8 +3331,8 @@ bool CWallet::InitLoadWallet()
if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && walletInstance->hdChain.masterKeyID.IsNull()) { if (GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET) && walletInstance->hdChain.masterKeyID.IsNull()) {
// generate a new master key // generate a new master key
CKey key; CKey key;
key.MakeNewKey(true); CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey();
if (!walletInstance->SetHDMasterKey(key)) if (!walletInstance->SetHDMasterKey(masterPubKey))
throw std::runtime_error("CWallet::GenerateNewKey(): Storing master key failed"); throw std::runtime_error("CWallet::GenerateNewKey(): Storing master key failed");
} }
CPubKey newDefaultKey; CPubKey newDefaultKey;

5
src/wallet/wallet.h

@ -901,8 +901,11 @@ public:
bool SetHDChain(const CHDChain& chain, bool memonly); bool SetHDChain(const CHDChain& chain, bool memonly);
const CHDChain& GetHDChain() { return hdChain; } 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) */ /* 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. */ /** A key allocated from the key pool. */

Loading…
Cancel
Save