From c141d9fef46b607474d4c1f48d4452f32d415e60 Mon Sep 17 00:00:00 2001 From: "Wladimir J. van der Laan" Date: Tue, 12 Dec 2017 19:48:24 +0100 Subject: [PATCH] Merge #11854: Split up key and script metadata for better type safety 9c8eca7 Split up key and script metadata for better type safety (Russell Yanofsky) Pull request description: Suggested by @TheBlueMatt https://github.com/bitcoin/bitcoin/pull/11403#discussion_r155599383 Combining the maps was probably never a good arrangement but is more problematic now in presence of WitnessV0ScriptHash and WitnessV0KeyHash types. Tree-SHA512: 9263e9c01090fb49221e91d88a88241a9691dda3e92d86041c8e284306a64d3af5e2438249f9dcc3e6e4a5c11c1a89f975a86d55690adf95bf2636f15f99f92a --- src/rpc/misc.cpp | 28 ++++++++++++++++++---------- src/wallet/wallet.cpp | 14 +++++++++++--- src/wallet/wallet.h | 11 +++++++---- src/wallet/walletdb.cpp | 30 +++++++++++++----------------- 4 files changed, 49 insertions(+), 34 deletions(-) diff --git a/src/rpc/misc.cpp b/src/rpc/misc.cpp index d5cdaecec2..7b2b4b750b 100644 --- a/src/rpc/misc.cpp +++ b/src/rpc/misc.cpp @@ -304,20 +304,28 @@ UniValue validateaddress(const JSONRPCRequest& request) ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name)); } if (pwallet) { - const auto& meta = pwallet->mapKeyMetadata; + const CKeyMetadata* meta = nullptr; const CKeyID *keyID = boost::get(&dest); - auto it = keyID ? meta.find(*keyID) : meta.end(); - if (it == meta.end()) { - it = meta.find(CScriptID(scriptPubKey)); + if (const CKeyID* key_id = boost::get(&dest)) { + auto it = pwallet->mapKeyMetadata.find(*key_id); + if (it != pwallet->mapKeyMetadata.end()) { + meta = &it->second; + } } - if (it != meta.end()) { - ret.push_back(Pair("timestamp", it->second.nCreateTime)); + if (!meta) { + auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey)); + if (it != pwallet->m_script_metadata.end()) { + meta = &it->second; + } } + if (meta) { + ret.push_back(Pair("timestamp", meta->nCreateTime)); + CHDChain hdChainCurrent; + if (pwallet->mapHdPubKeys.count(*keyID) && pwallet->GetHDChain(hdChainCurrent)) { + ret.push_back(Pair("hdkeypath", pwallet->mapHdPubKeys[*keyID].GetKeyPath())); + ret.push_back(Pair("hdchainid", hdChainCurrent.GetID().GetHex())); + } - CHDChain hdChainCurrent; - if (keyID && pwallet->mapHdPubKeys.count(*keyID) && pwallet->GetHDChain(hdChainCurrent)) { - ret.push_back(Pair("hdkeypath", pwallet->mapHdPubKeys[*keyID].GetKeyPath())); - ret.push_back(Pair("hdchainid", hdChainCurrent.GetID().GetHex())); } } #endif diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 748978ac98..896b9ec5c0 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -387,7 +387,7 @@ bool CWallet::AddCryptedKey(const CPubKey &vchPubKey, } } -bool CWallet::LoadKeyMetadata(const CTxDestination& keyID, const CKeyMetadata &meta) +bool CWallet::LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &meta) { AssertLockHeld(cs_wallet); // mapKeyMetadata UpdateTimeFirstKey(meta.nCreateTime); @@ -395,6 +395,14 @@ bool CWallet::LoadKeyMetadata(const CTxDestination& keyID, const CKeyMetadata &m return true; } +bool CWallet::LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &meta) +{ + AssertLockHeld(cs_wallet); // m_script_metadata + UpdateTimeFirstKey(meta.nCreateTime); + m_script_metadata[script_id] = meta; + return true; +} + bool CWallet::LoadCryptedKey(const CPubKey &vchPubKey, const std::vector &vchCryptedSecret) { return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret); @@ -443,7 +451,7 @@ bool CWallet::AddWatchOnly(const CScript& dest) { if (!CCryptoKeyStore::AddWatchOnly(dest)) return false; - const CKeyMetadata& meta = mapKeyMetadata[CScriptID(dest)]; + const CKeyMetadata& meta = m_script_metadata[CScriptID(dest)]; UpdateTimeFirstKey(meta.nCreateTime); NotifyWatchonlyChanged(true); return CWalletDB(*dbw).WriteWatchOnly(dest, meta); @@ -451,7 +459,7 @@ bool CWallet::AddWatchOnly(const CScript& dest) bool CWallet::AddWatchOnly(const CScript& dest, int64_t nCreateTime) { - mapKeyMetadata[CScriptID(dest)].nCreateTime = nCreateTime; + m_script_metadata[CScriptID(dest)].nCreateTime = nCreateTime; return AddWatchOnly(dest); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 2d0e0e9e45..f40ff377b7 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -824,9 +824,11 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface void LoadKeyPool(int64_t nIndex, const CKeyPool &keypool); - // Map from Key ID (for regular keys) or Script ID (for watch-only keys) to - // key metadata. - std::map mapKeyMetadata; + // Map from Key ID to key metadata. + std::map mapKeyMetadata; + + // Map from Script ID to key metadata (for watch-only keys). + std::map m_script_metadata; typedef std::map MasterKeyMap; MasterKeyMap mapMasterKeys; @@ -978,7 +980,8 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface //! Adds a key to the store, without saving it to disk (used by LoadWallet) bool LoadKey(const CKey& key, const CPubKey &pubkey) { return CCryptoKeyStore::AddKeyPubKey(key, pubkey); } //! Load metadata (used by LoadWallet) - bool LoadKeyMetadata(const CTxDestination& pubKey, const CKeyMetadata &metadata); + bool LoadKeyMetadata(const CKeyID& keyID, const CKeyMetadata &metadata); + bool LoadScriptMetadata(const CScriptID& script_id, const CKeyMetadata &metadata); bool LoadMinVersion(int nVersion) { AssertLockHeld(cs_wallet); nWalletVersion = nVersion; nWalletMaxVersion = std::max(nWalletMaxVersion, nVersion); return true; } void UpdateTimeFirstKey(int64_t nCreateTime); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 8df2a14a9a..ad455cf8c8 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -426,27 +426,23 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue, } wss.fIsEncrypted = true; } - else if (strType == "keymeta" || strType == "watchmeta") + else if (strType == "keymeta") { - CTxDestination keyID; - if (strType == "keymeta") - { - CPubKey vchPubKey; - ssKey >> vchPubKey; - keyID = vchPubKey.GetID(); - } - else if (strType == "watchmeta") - { - CScript script; - ssKey >> script; - keyID = CScriptID(script); - } - + CPubKey vchPubKey; + ssKey >> vchPubKey; CKeyMetadata keyMeta; ssValue >> keyMeta; wss.nKeyMeta++; - - pwallet->LoadKeyMetadata(keyID, keyMeta); + pwallet->LoadKeyMetadata(vchPubKey.GetID(), keyMeta); + } + else if (strType == "watchmeta") + { + CScript script; + ssKey >> script; + CKeyMetadata keyMeta; + ssValue >> keyMeta; + wss.nKeyMeta++; + pwallet->LoadScriptMetadata(CScriptID(script), keyMeta); } else if (strType == "defaultkey") {