Skip to content

Commit

Permalink
Merge #11854: Split up key and script metadata for better type safety
Browse files Browse the repository at this point in the history
9c8eca7 Split up key and script metadata for better type safety (Russell Yanofsky)

Pull request description:

  Suggested by @TheBlueMatt
  #11403 (comment)

  Combining the maps was probably never a good arrangement but is more
  problematic now in presence of WitnessV0ScriptHash and WitnessV0KeyHash types.

Tree-SHA512: 9263e9c01090fb49221e91d88a88241a9691dda3e92d86041c8e284306a64d3af5e2438249f9dcc3e6e4a5c11c1a89f975a86d55690adf95bf2636f15f99f92a
  • Loading branch information
laanwj committed Dec 12, 2017
2 parents 5d132e8 + 9c8eca7 commit 2214954
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 34 deletions.
27 changes: 17 additions & 10 deletions src/rpc/misc.cpp
Expand Up @@ -187,17 +187,24 @@ UniValue validateaddress(const JSONRPCRequest& request)
ret.push_back(Pair("account", pwallet->mapAddressBook[dest].name));
}
if (pwallet) {
const auto& meta = pwallet->mapKeyMetadata;
const CKeyID *keyID = boost::get<CKeyID>(&dest);
auto it = keyID ? meta.find(*keyID) : meta.end();
if (it == meta.end()) {
it = meta.find(CScriptID(scriptPubKey));
const CKeyMetadata* meta = nullptr;
if (const CKeyID* key_id = boost::get<CKeyID>(&dest)) {
auto it = pwallet->mapKeyMetadata.find(*key_id);
if (it != pwallet->mapKeyMetadata.end()) {
meta = &it->second;
}
}
if (!meta) {
auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey));
if (it != pwallet->m_script_metadata.end()) {
meta = &it->second;
}
}
if (it != meta.end()) {
ret.push_back(Pair("timestamp", it->second.nCreateTime));
if (!it->second.hdKeypath.empty()) {
ret.push_back(Pair("hdkeypath", it->second.hdKeypath));
ret.push_back(Pair("hdmasterkeyid", it->second.hdMasterKeyID.GetHex()));
if (meta) {
ret.push_back(Pair("timestamp", meta->nCreateTime));
if (!meta->hdKeypath.empty()) {
ret.push_back(Pair("hdkeypath", meta->hdKeypath));
ret.push_back(Pair("hdmasterkeyid", meta->hdMasterKeyID.GetHex()));
}
}
}
Expand Down
14 changes: 11 additions & 3 deletions src/wallet/wallet.cpp
Expand Up @@ -282,14 +282,22 @@ 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);
mapKeyMetadata[keyID] = meta;
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<unsigned char> &vchCryptedSecret)
{
return CCryptoKeyStore::AddCryptedKey(vchPubKey, vchCryptedSecret);
Expand Down Expand Up @@ -338,15 +346,15 @@ 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);
}

bool CWallet::AddWatchOnly(const CScript& dest, int64_t nCreateTime)
{
mapKeyMetadata[CScriptID(dest)].nCreateTime = nCreateTime;
m_script_metadata[CScriptID(dest)].nCreateTime = nCreateTime;
return AddWatchOnly(dest);
}

Expand Down
11 changes: 7 additions & 4 deletions src/wallet/wallet.h
Expand Up @@ -761,9 +761,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<CTxDestination, CKeyMetadata> mapKeyMetadata;
// Map from Key ID to key metadata.
std::map<CKeyID, CKeyMetadata> mapKeyMetadata;

// Map from Script ID to key metadata (for watch-only keys).
std::map<CScriptID, CKeyMetadata> m_script_metadata;

typedef std::map<unsigned int, CMasterKey> MasterKeyMap;
MasterKeyMap mapMasterKeys;
Expand Down Expand Up @@ -874,7 +876,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);
Expand Down
30 changes: 13 additions & 17 deletions src/wallet/walletdb.cpp
Expand Up @@ -423,27 +423,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")
{
Expand Down

0 comments on commit 2214954

Please sign in to comment.