From 131d4450b913fa4f00dc8b176dc996d39f786c19 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Wed, 4 Apr 2018 11:43:45 -0400 Subject: [PATCH 1/4] scripted-diff: Rename master key to seed -BEGIN VERIFY SCRIPT- ren() { git grep -l "\<$1\>" 'src/*.cpp' 'src/*.h' test | xargs sed -i "s:\<$1\>:$2:g"; } ren GenerateNewHDMasterKey GenerateNewSeed ren DeriveNewMasterHDKey DeriveNewSeed ren SetHDMasterKey SetHDSeed ren hdMasterKeyID hd_seed_id ren masterKeyID seed_id ren SetMaster SetSeed ren hdmasterkeyid hdseedid ren hdmaster hdseed -END VERIFY SCRIPT- --- src/key.cpp | 2 +- src/key.h | 2 +- src/test/bip32_tests.cpp | 2 +- src/wallet/rpcdump.cpp | 12 ++++++------ src/wallet/rpcwallet.cpp | 24 ++++++++++++------------ src/wallet/wallet.cpp | 30 +++++++++++++++--------------- src/wallet/wallet.h | 6 +++--- src/wallet/walletdb.h | 12 ++++++------ test/functional/wallet_dump.py | 2 +- test/functional/wallet_hd.py | 16 ++++++++-------- test/functional/wallet_keypool.py | 6 +++--- 11 files changed, 57 insertions(+), 57 deletions(-) diff --git a/src/key.cpp b/src/key.cpp index 042e68777..94be179bf 100644 --- a/src/key.cpp +++ b/src/key.cpp @@ -273,7 +273,7 @@ bool CExtKey::Derive(CExtKey &out, unsigned int _nChild) const { return key.Derive(out.key, out.chaincode, _nChild, chaincode); } -void CExtKey::SetMaster(const unsigned char *seed, unsigned int nSeedLen) { +void CExtKey::SetSeed(const unsigned char *seed, unsigned int nSeedLen) { static const unsigned char hashkey[] = {'B','i','t','c','o','i','n',' ','s','e','e','d'}; std::vector> vout(64); CHMAC_SHA512(hashkey, sizeof(hashkey)).Write(seed, nSeedLen).Finalize(vout.data()); diff --git a/src/key.h b/src/key.h index 3c0a7574f..f573a18a4 100644 --- a/src/key.h +++ b/src/key.h @@ -158,7 +158,7 @@ struct CExtKey { void Decode(const unsigned char code[BIP32_EXTKEY_SIZE]); bool Derive(CExtKey& out, unsigned int nChild) const; CExtPubKey Neuter() const; - void SetMaster(const unsigned char* seed, unsigned int nSeedLen); + void SetSeed(const unsigned char* seed, unsigned int nSeedLen); template void Serialize(Stream& s) const { diff --git a/src/test/bip32_tests.cpp b/src/test/bip32_tests.cpp index 51308847f..2c625c089 100644 --- a/src/test/bip32_tests.cpp +++ b/src/test/bip32_tests.cpp @@ -91,7 +91,7 @@ static void RunTest(const TestVector &test) { std::vector seed = ParseHex(test.strHexMaster); CExtKey key; CExtPubKey pubkey; - key.SetMaster(seed.data(), seed.size()); + key.SetSeed(seed.data(), seed.size()); pubkey = key.Neuter(); for (const TestDerivation &derive : test.vDerive) { unsigned char data[74]; diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 4fe630b66..256a5576f 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -752,13 +752,13 @@ UniValue dumpwallet(const JSONRPCRequest& request) file << "\n"; // add the base58check encoded extended master if the wallet uses HD - CKeyID masterKeyID = pwallet->GetHDChain().masterKeyID; - if (!masterKeyID.IsNull()) + CKeyID seed_id = pwallet->GetHDChain().seed_id; + if (!seed_id.IsNull()) { CKey key; - if (pwallet->GetKey(masterKeyID, key)) { + if (pwallet->GetKey(seed_id, key)) { CExtKey masterKey; - masterKey.SetMaster(key.begin(), key.size()); + masterKey.SetSeed(key.begin(), key.size()); file << "# extended private masterkey: " << EncodeExtKey(masterKey) << "\n\n"; } @@ -773,8 +773,8 @@ UniValue dumpwallet(const JSONRPCRequest& request) file << strprintf("%s %s ", EncodeSecret(key), strTime); if (GetWalletAddressesForKey(pwallet, keyid, strAddr, strLabel)) { file << strprintf("label=%s", strLabel); - } else if (keyid == masterKeyID) { - file << "hdmaster=1"; + } else if (keyid == seed_id) { + file << "hdseed=1"; } else if (mapKeyPool.count(keyid)) { file << "reserve=1"; } else if (pwallet->mapKeyMetadata[keyid].hdKeypath == "m") { diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 8cd395283..3b7537d7b 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2925,7 +2925,7 @@ static UniValue getwalletinfo(const JSONRPCRequest& request) " \"keypoolsize_hd_internal\": xxxx, (numeric) how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)\n" " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n" " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n" - " \"hdmasterkeyid\": \"\" (string, optional) the Hash160 of the HD master pubkey (only present when HD is enabled)\n" + " \"hdseedid\": \"\" (string, optional) the Hash160 of the HD master pubkey (only present when HD is enabled)\n" "}\n" "\nExamples:\n" + HelpExampleCli("getwalletinfo", "") @@ -2949,16 +2949,16 @@ static UniValue getwalletinfo(const JSONRPCRequest& request) obj.pushKV("txcount", (int)pwallet->mapWallet.size()); obj.pushKV("keypoololdest", pwallet->GetOldestKeyPoolTime()); obj.pushKV("keypoolsize", (int64_t)kpExternalSize); - CKeyID masterKeyID = pwallet->GetHDChain().masterKeyID; - if (!masterKeyID.IsNull() && pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) { + CKeyID seed_id = pwallet->GetHDChain().seed_id; + if (!seed_id.IsNull() && pwallet->CanSupportFeature(FEATURE_HD_SPLIT)) { obj.pushKV("keypoolsize_hd_internal", (int64_t)(pwallet->GetKeyPoolSize() - kpExternalSize)); } if (pwallet->IsCrypted()) { obj.pushKV("unlocked_until", pwallet->nRelockTime); } obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK())); - if (!masterKeyID.IsNull()) - obj.pushKV("hdmasterkeyid", masterKeyID.GetHex()); + if (!seed_id.IsNull()) + obj.pushKV("hdseedid", seed_id.GetHex()); return obj; } @@ -3948,13 +3948,13 @@ UniValue getaddressinfo(const JSONRPCRequest& request) " ]\n" " \"sigsrequired\" : xxxxx (numeric, optional) Number of signatures required to spend multisig output (only if \"script\" is \"multisig\")\n" " \"pubkey\" : \"publickeyhex\", (string, optional) The hex value of the raw public key, for single-key addresses (possibly embedded in P2SH or P2WSH)\n" - " \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH or P2WSH, if relevant and known. It includes all getaddressinfo output fields for the embedded address, excluding metadata (\"timestamp\", \"hdkeypath\", \"hdmasterkeyid\") and relation to the wallet (\"ismine\", \"iswatchonly\", \"account\").\n" + " \"embedded\" : {...}, (object, optional) Information about the address embedded in P2SH or P2WSH, if relevant and known. It includes all getaddressinfo output fields for the embedded address, excluding metadata (\"timestamp\", \"hdkeypath\", \"hdseedid\") and relation to the wallet (\"ismine\", \"iswatchonly\", \"account\").\n" " \"iscompressed\" : true|false, (boolean) If the address is compressed\n" " \"label\" : \"label\" (string) The label associated with the address, \"\" is the default account\n" " \"account\" : \"account\" (string) DEPRECATED. This field will be removed in V0.18. To see this deprecated field, start bitcoind with -deprecatedrpc=accounts. The account associated with the address, \"\" is the default account\n" " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n" " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n" - " \"hdmasterkeyid\" : \"\" (string, optional) The Hash160 of the HD master pubkey\n" + " \"hdseedid\" : \"\" (string, optional) The Hash160 of the HD master pubkey\n" " \"labels\" (object) Array of labels associated with the address.\n" " [\n" " { (json object of label data)\n" @@ -4014,7 +4014,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request) ret.pushKV("timestamp", meta->nCreateTime); if (!meta->hdKeypath.empty()) { ret.pushKV("hdkeypath", meta->hdKeypath); - ret.pushKV("hdmasterkeyid", meta->hdMasterKeyID.GetHex()); + ret.pushKV("hdseedid", meta->hd_seed_id.GetHex()); } } @@ -4147,7 +4147,7 @@ UniValue sethdseed(const JSONRPCRequest& request) " If false, addresses (including change addresses if the wallet already had HD Chain Split enabled) from the existing\n" " keypool will be used until it has been depleted.\n" "2. \"seed\" (string, optional) The WIF private key to use as the new HD seed; if not provided a random seed will be used.\n" - " The seed value can be retrieved using the dumpwallet command. It is the private key marked hdmaster=1\n" + " The seed value can be retrieved using the dumpwallet command. It is the private key marked hdseed=1\n" "\nExamples:\n" + HelpExampleCli("sethdseed", "") + HelpExampleCli("sethdseed", "false") @@ -4176,7 +4176,7 @@ UniValue sethdseed(const JSONRPCRequest& request) CPubKey master_pub_key; if (request.params[1].isNull()) { - master_pub_key = pwallet->GenerateNewHDMasterKey(); + master_pub_key = pwallet->GenerateNewSeed(); } else { CKey key = DecodeSecret(request.params[1].get_str()); if (!key.IsValid()) { @@ -4187,10 +4187,10 @@ UniValue sethdseed(const JSONRPCRequest& request) throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Already have this key (either as an HD seed or as a loose private key)"); } - master_pub_key = pwallet->DeriveNewMasterHDKey(key); + master_pub_key = pwallet->DeriveNewSeed(key); } - pwallet->SetHDMasterKey(master_pub_key); + pwallet->SetHDSeed(master_pub_key); if (flush_key_pool) pwallet->NewKeyPool(); return NullUniValue; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 2a2f8b5b2..27d1427e3 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -198,10 +198,10 @@ void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey CExtKey childKey; //key at m/0'/0'/' // try to get the master key - if (!GetKey(hdChain.masterKeyID, key)) + if (!GetKey(hdChain.seed_id, key)) throw std::runtime_error(std::string(__func__) + ": Master key not found"); - masterKey.SetMaster(key.begin(), key.size()); + masterKey.SetSeed(key.begin(), key.size()); // derive m/0' // use hardened derivation (child keys >= 0x80000000 are hardened after bip32) @@ -228,7 +228,7 @@ void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey } } while (HaveKey(childKey.key.GetPubKey().GetID())); secret = childKey.key; - metadata.hdMasterKeyID = hdChain.masterKeyID; + metadata.hd_seed_id = hdChain.seed_id; // update the chain model in the database if (!batch.WriteHDChain(hdChain)) throw std::runtime_error(std::string(__func__) + ": Writing HD chain model failed"); @@ -691,7 +691,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) // if we are using HD, replace the HD master key (seed) with a new one if (IsHDEnabled()) { - if (!SetHDMasterKey(GenerateNewHDMasterKey())) { + if (!SetHDSeed(GenerateNewSeed())) { return false; } } @@ -1450,14 +1450,14 @@ CAmount CWallet::GetChange(const CTransaction& tx) const return nChange; } -CPubKey CWallet::GenerateNewHDMasterKey() +CPubKey CWallet::GenerateNewSeed() { CKey key; key.MakeNewKey(true); - return DeriveNewMasterHDKey(key); + return DeriveNewSeed(key); } -CPubKey CWallet::DeriveNewMasterHDKey(const CKey& key) +CPubKey CWallet::DeriveNewSeed(const CKey& key) { int64_t nCreationTime = GetTime(); CKeyMetadata metadata(nCreationTime); @@ -1468,7 +1468,7 @@ CPubKey CWallet::DeriveNewMasterHDKey(const CKey& key) // set the hd keypath to "m" -> Master, refers the masterkeyid to itself metadata.hdKeypath = "m"; - metadata.hdMasterKeyID = pubkey.GetID(); + metadata.hd_seed_id = pubkey.GetID(); { LOCK(cs_wallet); @@ -1484,7 +1484,7 @@ CPubKey CWallet::DeriveNewMasterHDKey(const CKey& key) return pubkey; } -bool CWallet::SetHDMasterKey(const CPubKey& pubkey) +bool CWallet::SetHDSeed(const CPubKey& pubkey) { LOCK(cs_wallet); // store the keyid (hash160) together with @@ -1492,7 +1492,7 @@ bool CWallet::SetHDMasterKey(const CPubKey& pubkey) // as a hdchain object CHDChain newHdChain; newHdChain.nVersion = CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE; - newHdChain.masterKeyID = pubkey.GetID(); + newHdChain.seed_id = pubkey.GetID(); SetHDChain(newHdChain, false); return true; @@ -1510,7 +1510,7 @@ bool CWallet::SetHDChain(const CHDChain& chain, bool memonly) bool CWallet::IsHDEnabled() const { - return !hdChain.masterKeyID.IsNull(); + return !hdChain.seed_id.IsNull(); } int64_t CWalletTx::GetTxTime() const @@ -4130,8 +4130,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& walletInstance->SetMinVersion(FEATURE_HD); // generate a new master key - CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey(); - if (!walletInstance->SetHDMasterKey(masterPubKey)) { + CPubKey masterPubKey = walletInstance->GenerateNewSeed(); + if (!walletInstance->SetHDSeed(masterPubKey)) { throw std::runtime_error(std::string(__func__) + ": Storing master key failed"); } hd_upgrade = true; @@ -4165,8 +4165,8 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& walletInstance->SetMinVersion(FEATURE_LATEST); // generate a new master key - CPubKey masterPubKey = walletInstance->GenerateNewHDMasterKey(); - if (!walletInstance->SetHDMasterKey(masterPubKey)) + CPubKey masterPubKey = walletInstance->GenerateNewSeed(); + if (!walletInstance->SetHDSeed(masterPubKey)) throw std::runtime_error(std::string(__func__) + ": Storing master key failed"); // Top up the keypool diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index fecc2178e..938f954e2 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1140,16 +1140,16 @@ public: bool IsHDEnabled() const; /* Generates a new HD master key (will not be activated) */ - CPubKey GenerateNewHDMasterKey(); + CPubKey GenerateNewSeed(); /* Derives a new HD master key (will not be activated) */ - CPubKey DeriveNewMasterHDKey(const CKey& key); + CPubKey DeriveNewSeed(const CKey& key); /* Set the current HD master key (will reset the chain child index counters) Sets the master key's version based on the current wallet version (so the caller must ensure the current wallet version is correct before calling this function). */ - bool SetHDMasterKey(const CPubKey& key); + bool SetHDSeed(const CPubKey& key); /** * Blocks until the wallet state is up-to-date to /at least/ the current diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index a73d727c0..226e18cf1 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -62,7 +62,7 @@ class CHDChain public: uint32_t nExternalChainCounter; uint32_t nInternalChainCounter; - CKeyID masterKeyID; //!< master key hash160 + CKeyID seed_id; //!< master key hash160 static const int VERSION_HD_BASE = 1; static const int VERSION_HD_CHAIN_SPLIT = 2; @@ -76,7 +76,7 @@ public: { READWRITE(this->nVersion); READWRITE(nExternalChainCounter); - READWRITE(masterKeyID); + READWRITE(seed_id); if (this->nVersion >= VERSION_HD_CHAIN_SPLIT) READWRITE(nInternalChainCounter); } @@ -86,7 +86,7 @@ public: nVersion = CHDChain::CURRENT_VERSION; nExternalChainCounter = 0; nInternalChainCounter = 0; - masterKeyID.SetNull(); + seed_id.SetNull(); } }; @@ -99,7 +99,7 @@ public: int nVersion; int64_t nCreateTime; // 0 means unknown std::string hdKeypath; //optional HD/bip32 keypath - CKeyID hdMasterKeyID; //id of the HD masterkey used to derive this key + CKeyID hd_seed_id; //id of the HD masterkey used to derive this key CKeyMetadata() { @@ -120,7 +120,7 @@ public: if (this->nVersion >= VERSION_WITH_HDDATA) { READWRITE(hdKeypath); - READWRITE(hdMasterKeyID); + READWRITE(hd_seed_id); } } @@ -129,7 +129,7 @@ public: nVersion = CKeyMetadata::CURRENT_VERSION; nCreateTime = 0; hdKeypath.clear(); - hdMasterKeyID.SetNull(); + hd_seed_id.SetNull(); } }; diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py index 01d27dabe..6c2590812 100755 --- a/test/functional/wallet_dump.py +++ b/test/functional/wallet_dump.py @@ -39,7 +39,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old): if keytype == "inactivehdmaster=1": # ensure the old master is still available assert(hd_master_addr_old == addr) - elif keytype == "hdmaster=1": + elif keytype == "hdseed=1": # ensure we have generated a new hd master key assert(hd_master_addr_old != addr) hd_master_addr_ret = addr diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py index 97a945721..afc20c5a9 100755 --- a/test/functional/wallet_hd.py +++ b/test/functional/wallet_hd.py @@ -29,7 +29,7 @@ class WalletHDTest(BitcoinTestFramework): connect_nodes_bi(self.nodes, 0, 1) # Make sure we use hd, keep masterkeyid - masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid'] + masterkeyid = self.nodes[1].getwalletinfo()['hdseedid'] assert_equal(len(masterkeyid), 40) # create an internal key @@ -54,7 +54,7 @@ class WalletHDTest(BitcoinTestFramework): hd_add = self.nodes[1].getnewaddress() hd_info = self.nodes[1].getaddressinfo(hd_add) assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(i)+"'") - assert_equal(hd_info["hdmasterkeyid"], masterkeyid) + assert_equal(hd_info["hdseedid"], masterkeyid) self.nodes[0].sendtoaddress(hd_add, 1) self.nodes[0].generate(1) self.nodes[0].sendtoaddress(non_hd_add, 1) @@ -83,7 +83,7 @@ class WalletHDTest(BitcoinTestFramework): hd_add_2 = self.nodes[1].getnewaddress() hd_info_2 = self.nodes[1].getaddressinfo(hd_add_2) assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/"+str(i)+"'") - assert_equal(hd_info_2["hdmasterkeyid"], masterkeyid) + assert_equal(hd_info_2["hdseedid"], masterkeyid) assert_equal(hd_add, hd_add_2) connect_nodes_bi(self.nodes, 0, 1) self.sync_all() @@ -122,9 +122,9 @@ class WalletHDTest(BitcoinTestFramework): assert_equal(keypath[0:7], "m/0'/1'") # Generate a new HD seed on node 1 and make sure it is set - orig_masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid'] + orig_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid'] self.nodes[1].sethdseed() - new_masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid'] + new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid'] assert orig_masterkeyid != new_masterkeyid addr = self.nodes[1].getnewaddress() assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is the first from the keypool @@ -134,16 +134,16 @@ class WalletHDTest(BitcoinTestFramework): new_seed = self.nodes[0].dumpprivkey(self.nodes[0].getnewaddress()) orig_masterkeyid = new_masterkeyid self.nodes[1].sethdseed(False, new_seed) - new_masterkeyid = self.nodes[1].getwalletinfo()['hdmasterkeyid'] + new_masterkeyid = self.nodes[1].getwalletinfo()['hdseedid'] assert orig_masterkeyid != new_masterkeyid addr = self.nodes[1].getnewaddress() - assert_equal(orig_masterkeyid, self.nodes[1].getaddressinfo(addr)['hdmasterkeyid']) + assert_equal(orig_masterkeyid, self.nodes[1].getaddressinfo(addr)['hdseedid']) assert_equal(self.nodes[1].getaddressinfo(addr)['hdkeypath'], 'm/0\'/0\'/1\'') # Make sure the new address continues previous keypool # Check that the next address is from the new seed self.nodes[1].keypoolrefill(1) next_addr = self.nodes[1].getnewaddress() - assert_equal(new_masterkeyid, self.nodes[1].getaddressinfo(next_addr)['hdmasterkeyid']) + assert_equal(new_masterkeyid, self.nodes[1].getaddressinfo(next_addr)['hdseedid']) assert_equal(self.nodes[1].getaddressinfo(next_addr)['hdkeypath'], 'm/0\'/0\'/0\'') # Make sure the new address is not from previous keypool assert next_addr != addr diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py index 505014e48..66d382e4c 100755 --- a/test/functional/wallet_keypool.py +++ b/test/functional/wallet_keypool.py @@ -16,7 +16,7 @@ class KeyPoolTest(BitcoinTestFramework): addr_before_encrypting = nodes[0].getnewaddress() addr_before_encrypting_data = nodes[0].getaddressinfo(addr_before_encrypting) wallet_info_old = nodes[0].getwalletinfo() - assert(addr_before_encrypting_data['hdmasterkeyid'] == wallet_info_old['hdmasterkeyid']) + assert(addr_before_encrypting_data['hdseedid'] == wallet_info_old['hdseedid']) # Encrypt wallet and wait to terminate nodes[0].node_encrypt_wallet('test') @@ -26,8 +26,8 @@ class KeyPoolTest(BitcoinTestFramework): addr = nodes[0].getnewaddress() addr_data = nodes[0].getaddressinfo(addr) wallet_info = nodes[0].getwalletinfo() - assert(addr_before_encrypting_data['hdmasterkeyid'] != wallet_info['hdmasterkeyid']) - assert(addr_data['hdmasterkeyid'] == wallet_info['hdmasterkeyid']) + assert(addr_before_encrypting_data['hdseedid'] != wallet_info['hdseedid']) + assert(addr_data['hdseedid'] == wallet_info['hdseedid']) assert_raises_rpc_error(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress) # put six (plus 2) new keys in the keypool (100% external-, +100% internal-keys, 1 in min) From c75c351419dac3dfe9578604ea5b2f7599452b4a Mon Sep 17 00:00:00 2001 From: John Newbery Date: Wed, 4 Apr 2018 12:47:55 -0400 Subject: [PATCH 2/4] [refactor] manually change remaining instances of master key to seed. --- src/wallet/rpcdump.cpp | 10 ++++---- src/wallet/rpcwallet.cpp | 4 ++-- src/wallet/wallet.cpp | 42 +++++++++++++++++----------------- src/wallet/wallet.h | 6 ++--- src/wallet/walletdb.h | 4 ++-- test/functional/wallet_dump.py | 2 +- 6 files changed, 34 insertions(+), 34 deletions(-) diff --git a/src/wallet/rpcdump.cpp b/src/wallet/rpcdump.cpp index 256a5576f..fc58af0da 100644 --- a/src/wallet/rpcdump.cpp +++ b/src/wallet/rpcdump.cpp @@ -755,10 +755,10 @@ UniValue dumpwallet(const JSONRPCRequest& request) CKeyID seed_id = pwallet->GetHDChain().seed_id; if (!seed_id.IsNull()) { - CKey key; - if (pwallet->GetKey(seed_id, key)) { + CKey seed; + if (pwallet->GetKey(seed_id, seed)) { CExtKey masterKey; - masterKey.SetSeed(key.begin(), key.size()); + masterKey.SetSeed(seed.begin(), seed.size()); file << "# extended private masterkey: " << EncodeExtKey(masterKey) << "\n\n"; } @@ -777,8 +777,8 @@ UniValue dumpwallet(const JSONRPCRequest& request) file << "hdseed=1"; } else if (mapKeyPool.count(keyid)) { file << "reserve=1"; - } else if (pwallet->mapKeyMetadata[keyid].hdKeypath == "m") { - file << "inactivehdmaster=1"; + } else if (pwallet->mapKeyMetadata[keyid].hdKeypath == "s") { + file << "inactivehdseed=1"; } else { file << "change=1"; } diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 3b7537d7b..eab345b17 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2925,7 +2925,7 @@ static UniValue getwalletinfo(const JSONRPCRequest& request) " \"keypoolsize_hd_internal\": xxxx, (numeric) how many new keys are pre-generated for internal use (used for change outputs, only appears if the wallet is using this feature, otherwise external keys are used)\n" " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n" " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n" - " \"hdseedid\": \"\" (string, optional) the Hash160 of the HD master pubkey (only present when HD is enabled)\n" + " \"hdseedid\": \"\" (string, optional) the Hash160 of the HD seed (only present when HD is enabled)\n" "}\n" "\nExamples:\n" + HelpExampleCli("getwalletinfo", "") @@ -3954,7 +3954,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request) " \"account\" : \"account\" (string) DEPRECATED. This field will be removed in V0.18. To see this deprecated field, start bitcoind with -deprecatedrpc=accounts. The account associated with the address, \"\" is the default account\n" " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n" " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n" - " \"hdseedid\" : \"\" (string, optional) The Hash160 of the HD master pubkey\n" + " \"hdseedid\" : \"\" (string, optional) The Hash160 of the HD seed\n" " \"labels\" (object) Array of labels associated with the address.\n" " [\n" " { (json object of label data)\n" diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 27d1427e3..abb87b192 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -191,17 +191,17 @@ CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal) void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata& metadata, CKey& secret, bool internal) { // for now we use a fixed keypath scheme of m/0'/0'/k - CKey key; //master key seed (256bit) + CKey seed; //seed (256bit) CExtKey masterKey; //hd master key CExtKey accountKey; //key at m/0' CExtKey chainChildKey; //key at m/0'/0' (external) or m/0'/1' (internal) CExtKey childKey; //key at m/0'/0'/' - // try to get the master key - if (!GetKey(hdChain.seed_id, key)) - throw std::runtime_error(std::string(__func__) + ": Master key not found"); + // try to get the seed + if (!GetKey(hdChain.seed_id, seed)) + throw std::runtime_error(std::string(__func__) + ": seed not found"); - masterKey.SetSeed(key.begin(), key.size()); + masterKey.SetSeed(seed.begin(), seed.size()); // derive m/0' // use hardened derivation (child keys >= 0x80000000 are hardened after bip32) @@ -689,7 +689,7 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase) Lock(); Unlock(strWalletPassphrase); - // if we are using HD, replace the HD master key (seed) with a new one + // if we are using HD, replace the HD seed with a new one if (IsHDEnabled()) { if (!SetHDSeed(GenerateNewSeed())) { return false; @@ -1462,29 +1462,29 @@ CPubKey CWallet::DeriveNewSeed(const CKey& key) int64_t nCreationTime = GetTime(); CKeyMetadata metadata(nCreationTime); - // calculate the pubkey - CPubKey pubkey = key.GetPubKey(); - assert(key.VerifyPubKey(pubkey)); + // calculate the seed + CPubKey seed = key.GetPubKey(); + assert(key.VerifyPubKey(seed)); - // set the hd keypath to "m" -> Master, refers the masterkeyid to itself - metadata.hdKeypath = "m"; - metadata.hd_seed_id = pubkey.GetID(); + // set the hd keypath to "s" -> Seed, refers the seed to itself + metadata.hdKeypath = "s"; + metadata.hd_seed_id = seed.GetID(); { LOCK(cs_wallet); // mem store the metadata - mapKeyMetadata[pubkey.GetID()] = metadata; + mapKeyMetadata[seed.GetID()] = metadata; // write the key&metadata to the database - if (!AddKeyPubKey(key, pubkey)) + if (!AddKeyPubKey(key, seed)) throw std::runtime_error(std::string(__func__) + ": AddKeyPubKey failed"); } - return pubkey; + return seed; } -bool CWallet::SetHDSeed(const CPubKey& pubkey) +bool CWallet::SetHDSeed(const CPubKey& seed) { LOCK(cs_wallet); // store the keyid (hash160) together with @@ -1492,7 +1492,7 @@ bool CWallet::SetHDSeed(const CPubKey& pubkey) // as a hdchain object CHDChain newHdChain; newHdChain.nVersion = CanSupportFeature(FEATURE_HD_SPLIT) ? CHDChain::VERSION_HD_CHAIN_SPLIT : CHDChain::VERSION_HD_BASE; - newHdChain.seed_id = pubkey.GetID(); + newHdChain.seed_id = seed.GetID(); SetHDChain(newHdChain, false); return true; @@ -4164,10 +4164,10 @@ CWallet* CWallet::CreateWalletFromFile(const std::string& name, const fs::path& } walletInstance->SetMinVersion(FEATURE_LATEST); - // generate a new master key - CPubKey masterPubKey = walletInstance->GenerateNewSeed(); - if (!walletInstance->SetHDSeed(masterPubKey)) - throw std::runtime_error(std::string(__func__) + ": Storing master key failed"); + // generate a new seed + CPubKey seed = walletInstance->GenerateNewSeed(); + if (!walletInstance->SetHDSeed(seed)) + throw std::runtime_error(std::string(__func__) + ": Storing HD seed failed"); // Top up the keypool if (!walletInstance->TopUpKeyPool()) { diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 938f954e2..142c54d7b 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1139,14 +1139,14 @@ public: /* Returns true if HD is enabled */ bool IsHDEnabled() const; - /* Generates a new HD master key (will not be activated) */ + /* Generates a new HD seed (will not be activated) */ CPubKey GenerateNewSeed(); /* Derives a new HD master key (will not be activated) */ CPubKey DeriveNewSeed(const CKey& key); - /* Set the current HD master key (will reset the chain child index counters) - Sets the master key's version based on the current wallet version (so the + /* Set the current HD seed (will reset the chain child index counters) + Sets the seed's version based on the current wallet version (so the caller must ensure the current wallet version is correct before calling this function). */ bool SetHDSeed(const CPubKey& key); diff --git a/src/wallet/walletdb.h b/src/wallet/walletdb.h index 226e18cf1..3237376f6 100644 --- a/src/wallet/walletdb.h +++ b/src/wallet/walletdb.h @@ -62,7 +62,7 @@ class CHDChain public: uint32_t nExternalChainCounter; uint32_t nInternalChainCounter; - CKeyID seed_id; //!< master key hash160 + CKeyID seed_id; //!< seed hash160 static const int VERSION_HD_BASE = 1; static const int VERSION_HD_CHAIN_SPLIT = 2; @@ -99,7 +99,7 @@ public: int nVersion; int64_t nCreateTime; // 0 means unknown std::string hdKeypath; //optional HD/bip32 keypath - CKeyID hd_seed_id; //id of the HD masterkey used to derive this key + CKeyID hd_seed_id; //id of the HD seed used to derive this key CKeyMetadata() { diff --git a/test/functional/wallet_dump.py b/test/functional/wallet_dump.py index 6c2590812..ba420ab2a 100755 --- a/test/functional/wallet_dump.py +++ b/test/functional/wallet_dump.py @@ -36,7 +36,7 @@ def read_dump(file_name, addrs, script_addrs, hd_master_addr_old): addr_keypath = comment.split(" addr=")[1] addr = addr_keypath.split(" ")[0] keypath = None - if keytype == "inactivehdmaster=1": + if keytype == "inactivehdseed=1": # ensure the old master is still available assert(hd_master_addr_old == addr) elif keytype == "hdseed=1": From 79053a5f2b26ee3dfd9a0bb3fd01ac4733fc92b5 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 17 Apr 2018 17:42:31 -0400 Subject: [PATCH 3/4] [rpc] [wallet] Add 'hdmasterkeyid' alias return values. Restores the return value in getwalletinfo() and getaddressinfo() RPC methods for backwards compatibility --- src/wallet/rpcwallet.cpp | 7 ++++++- test/functional/wallet_hd.py | 3 +++ test/functional/wallet_keypool.py | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index eab345b17..780c40629 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2926,6 +2926,7 @@ static UniValue getwalletinfo(const JSONRPCRequest& request) " \"unlocked_until\": ttt, (numeric) the timestamp in seconds since epoch (midnight Jan 1 1970 GMT) that the wallet is unlocked for transfers, or 0 if the wallet is locked\n" " \"paytxfee\": x.xxxx, (numeric) the transaction fee configuration, set in " + CURRENCY_UNIT + "/kB\n" " \"hdseedid\": \"\" (string, optional) the Hash160 of the HD seed (only present when HD is enabled)\n" + " \"hdmasterkeyid\": \"\" (string, optional) alias for hdseedid retained for backwards-compatibility. Will be removed in V0.18.\n" "}\n" "\nExamples:\n" + HelpExampleCli("getwalletinfo", "") @@ -2957,8 +2958,10 @@ static UniValue getwalletinfo(const JSONRPCRequest& request) obj.pushKV("unlocked_until", pwallet->nRelockTime); } obj.pushKV("paytxfee", ValueFromAmount(pwallet->m_pay_tx_fee.GetFeePerK())); - if (!seed_id.IsNull()) + if (!seed_id.IsNull()) { obj.pushKV("hdseedid", seed_id.GetHex()); + obj.pushKV("hdmasterkeyid", seed_id.GetHex()); + } return obj; } @@ -3955,6 +3958,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request) " \"timestamp\" : timestamp, (number, optional) The creation time of the key if available in seconds since epoch (Jan 1 1970 GMT)\n" " \"hdkeypath\" : \"keypath\" (string, optional) The HD keypath if the key is HD and available\n" " \"hdseedid\" : \"\" (string, optional) The Hash160 of the HD seed\n" + " \"hdmasterkeyid\" : \"\" (string, optional) alias for hdseedid maintained for backwards compatibility. Will be removed in V0.18.\n" " \"labels\" (object) Array of labels associated with the address.\n" " [\n" " { (json object of label data)\n" @@ -4015,6 +4019,7 @@ UniValue getaddressinfo(const JSONRPCRequest& request) if (!meta->hdKeypath.empty()) { ret.pushKV("hdkeypath", meta->hdKeypath); ret.pushKV("hdseedid", meta->hd_seed_id.GetHex()); + ret.pushKV("hdmasterkeyid", meta->hd_seed_id.GetHex()); } } diff --git a/test/functional/wallet_hd.py b/test/functional/wallet_hd.py index afc20c5a9..86abe0ca9 100755 --- a/test/functional/wallet_hd.py +++ b/test/functional/wallet_hd.py @@ -30,6 +30,7 @@ class WalletHDTest(BitcoinTestFramework): # Make sure we use hd, keep masterkeyid masterkeyid = self.nodes[1].getwalletinfo()['hdseedid'] + assert_equal(masterkeyid, self.nodes[1].getwalletinfo()['hdmasterkeyid']) assert_equal(len(masterkeyid), 40) # create an internal key @@ -55,6 +56,7 @@ class WalletHDTest(BitcoinTestFramework): hd_info = self.nodes[1].getaddressinfo(hd_add) assert_equal(hd_info["hdkeypath"], "m/0'/0'/"+str(i)+"'") assert_equal(hd_info["hdseedid"], masterkeyid) + assert_equal(hd_info["hdmasterkeyid"], masterkeyid) self.nodes[0].sendtoaddress(hd_add, 1) self.nodes[0].generate(1) self.nodes[0].sendtoaddress(non_hd_add, 1) @@ -84,6 +86,7 @@ class WalletHDTest(BitcoinTestFramework): hd_info_2 = self.nodes[1].getaddressinfo(hd_add_2) assert_equal(hd_info_2["hdkeypath"], "m/0'/0'/"+str(i)+"'") assert_equal(hd_info_2["hdseedid"], masterkeyid) + assert_equal(hd_info_2["hdmasterkeyid"], masterkeyid) assert_equal(hd_add, hd_add_2) connect_nodes_bi(self.nodes, 0, 1) self.sync_all() diff --git a/test/functional/wallet_keypool.py b/test/functional/wallet_keypool.py index 66d382e4c..1285515df 100755 --- a/test/functional/wallet_keypool.py +++ b/test/functional/wallet_keypool.py @@ -16,6 +16,7 @@ class KeyPoolTest(BitcoinTestFramework): addr_before_encrypting = nodes[0].getnewaddress() addr_before_encrypting_data = nodes[0].getaddressinfo(addr_before_encrypting) wallet_info_old = nodes[0].getwalletinfo() + assert_equal(wallet_info_old['hdseedid'], wallet_info_old['hdmasterkeyid']) assert(addr_before_encrypting_data['hdseedid'] == wallet_info_old['hdseedid']) # Encrypt wallet and wait to terminate @@ -26,6 +27,7 @@ class KeyPoolTest(BitcoinTestFramework): addr = nodes[0].getnewaddress() addr_data = nodes[0].getaddressinfo(addr) wallet_info = nodes[0].getwalletinfo() + assert_equal(wallet_info['hdseedid'], wallet_info['hdmasterkeyid']) assert(addr_before_encrypting_data['hdseedid'] != wallet_info['hdseedid']) assert(addr_data['hdseedid'] == wallet_info['hdseedid']) assert_raises_rpc_error(-12, "Error: Keypool ran out, please call keypoolrefill first", nodes[0].getnewaddress) From 6249021d152dec348eb4325c0dfccb3ba59f46d1 Mon Sep 17 00:00:00 2001 From: John Newbery Date: Tue, 17 Apr 2018 12:12:00 -0400 Subject: [PATCH 4/4] [docs] Add release notes for HD master key -> HD seed rename --- doc/release-notes-pr12924.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 doc/release-notes-pr12924.md diff --git a/doc/release-notes-pr12924.md b/doc/release-notes-pr12924.md new file mode 100644 index 000000000..92e7e2321 --- /dev/null +++ b/doc/release-notes-pr12924.md @@ -0,0 +1,12 @@ +RPC changes +------------ + +### Low-level changes + +- The `getwalletinfo` RPC method now returns an `hdseedid` value, which is always the same as the incorrectly-named `hdmasterkeyid` value. `hdmasterkeyid` will be removed in V0.18. +- The `getaddressinfo` RPC method now returns an `hdseedid` value, which is always the same as the incorrectly-named `hdmasterkeyid` value. `hdmasterkeyid` will be removed in V0.18. + +Other API changes +----------------- + +- The `inactivehdmaster` property in the `dumpwallet` output has been corrected to `inactivehdseed`