aboutsummaryrefslogtreecommitdiff
path: root/src/walletdb.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/walletdb.cpp')
-rw-r--r--src/walletdb.cpp38
1 files changed, 33 insertions, 5 deletions
diff --git a/src/walletdb.cpp b/src/walletdb.cpp
index 635fda1b42..efcd59d5f1 100644
--- a/src/walletdb.cpp
+++ b/src/walletdb.cpp
@@ -306,6 +306,8 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
}
CKey key;
CPrivKey pkey;
+ uint256 hash = 0;
+
if (strType == "key")
{
wss.nKeys++;
@@ -315,14 +317,40 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
ssValue >> wkey;
pkey = wkey.vchPrivKey;
}
- if (!key.SetPrivKey(pkey, vchPubKey.IsCompressed()))
+
+ // Old wallets store keys as "key" [pubkey] => [privkey]
+ // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
+ // using EC operations as a checksum.
+ // Newer wallets store keys as "key"[pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
+ // remaining backwards-compatible.
+ try
{
- strErr = "Error reading wallet database: CPrivKey corrupt";
- return false;
+ ssValue >> hash;
+ }
+ catch(...){}
+
+ bool fSkipCheck = false;
+
+ if (hash != 0)
+ {
+ // hash pubkey/privkey to accelerate wallet load
+ std::vector<unsigned char> vchKey;
+ vchKey.reserve(vchPubKey.size() + pkey.size());
+ vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end());
+ vchKey.insert(vchKey.end(), pkey.begin(), pkey.end());
+
+ if (Hash(vchKey.begin(), vchKey.end()) != hash)
+ {
+ strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt";
+ return false;
+ }
+
+ fSkipCheck = true;
}
- if (key.GetPubKey() != vchPubKey)
+
+ if (!key.Load(pkey, vchPubKey, fSkipCheck))
{
- strErr = "Error reading wallet database: CPrivKey pubkey inconsistency";
+ strErr = "Error reading wallet database: CPrivKey corrupt";
return false;
}
if (!pwallet->LoadKey(key, vchPubKey))