@@ -320,6 +320,72 @@ class CWalletScanState {
320
320
CWalletScanState () = default ;
321
321
};
322
322
323
+ bool LoadKey (CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::string& strErr)
324
+ {
325
+ LOCK (pwallet->cs_wallet );
326
+ try {
327
+ CPubKey vchPubKey;
328
+ ssKey >> vchPubKey;
329
+ if (!vchPubKey.IsValid ())
330
+ {
331
+ strErr = " Error reading wallet database: CPubKey corrupt" ;
332
+ return false ;
333
+ }
334
+ CKey key;
335
+ CPrivKey pkey;
336
+ uint256 hash;
337
+
338
+ ssValue >> pkey;
339
+
340
+ // Old wallets store keys as DBKeys::KEY [pubkey] => [privkey]
341
+ // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
342
+ // using EC operations as a checksum.
343
+ // Newer wallets store keys as DBKeys::KEY [pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
344
+ // remaining backwards-compatible.
345
+ try
346
+ {
347
+ ssValue >> hash;
348
+ }
349
+ catch (const std::ios_base::failure&) {}
350
+
351
+ bool fSkipCheck = false ;
352
+
353
+ if (!hash.IsNull ())
354
+ {
355
+ // hash pubkey/privkey to accelerate wallet load
356
+ std::vector<unsigned char > vchKey;
357
+ vchKey.reserve (vchPubKey.size () + pkey.size ());
358
+ vchKey.insert (vchKey.end (), vchPubKey.begin (), vchPubKey.end ());
359
+ vchKey.insert (vchKey.end (), pkey.begin (), pkey.end ());
360
+
361
+ if (Hash (vchKey) != hash)
362
+ {
363
+ strErr = " Error reading wallet database: CPubKey/CPrivKey corrupt" ;
364
+ return false ;
365
+ }
366
+
367
+ fSkipCheck = true ;
368
+ }
369
+
370
+ if (!key.Load (pkey, vchPubKey, fSkipCheck ))
371
+ {
372
+ strErr = " Error reading wallet database: CPrivKey corrupt" ;
373
+ return false ;
374
+ }
375
+ if (!pwallet->GetOrCreateLegacyScriptPubKeyMan ()->LoadKey (key, vchPubKey))
376
+ {
377
+ strErr = " Error reading wallet database: LegacyScriptPubKeyMan::LoadKey failed" ;
378
+ return false ;
379
+ }
380
+ } catch (const std::exception& e) {
381
+ if (strErr.empty ()) {
382
+ strErr = e.what ();
383
+ }
384
+ return false ;
385
+ }
386
+ return true ;
387
+ }
388
+
323
389
static bool
324
390
ReadKeyValue (CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue,
325
391
CWalletScanState &wss, std::string& strType, std::string& strErr, const KeyFilterFn& filter_fn = nullptr ) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet)
@@ -410,60 +476,8 @@ ReadKeyValue(CWallet* pwallet, DataStream& ssKey, CDataStream& ssValue,
410
476
pwallet->GetOrCreateLegacyScriptPubKeyMan ()->LoadWatchOnly (script);
411
477
}
412
478
} else if (strType == DBKeys::KEY) {
413
- CPubKey vchPubKey;
414
- ssKey >> vchPubKey;
415
- if (!vchPubKey.IsValid ())
416
- {
417
- strErr = " Error reading wallet database: CPubKey corrupt" ;
418
- return false ;
419
- }
420
- CKey key;
421
- CPrivKey pkey;
422
- uint256 hash;
423
-
424
479
wss.nKeys ++;
425
- ssValue >> pkey;
426
-
427
- // Old wallets store keys as DBKeys::KEY [pubkey] => [privkey]
428
- // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key
429
- // using EC operations as a checksum.
430
- // Newer wallets store keys as DBKeys::KEY [pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while
431
- // remaining backwards-compatible.
432
- try
433
- {
434
- ssValue >> hash;
435
- }
436
- catch (const std::ios_base::failure&) {}
437
-
438
- bool fSkipCheck = false ;
439
-
440
- if (!hash.IsNull ())
441
- {
442
- // hash pubkey/privkey to accelerate wallet load
443
- std::vector<unsigned char > vchKey;
444
- vchKey.reserve (vchPubKey.size () + pkey.size ());
445
- vchKey.insert (vchKey.end (), vchPubKey.begin (), vchPubKey.end ());
446
- vchKey.insert (vchKey.end (), pkey.begin (), pkey.end ());
447
-
448
- if (Hash (vchKey) != hash)
449
- {
450
- strErr = " Error reading wallet database: CPubKey/CPrivKey corrupt" ;
451
- return false ;
452
- }
453
-
454
- fSkipCheck = true ;
455
- }
456
-
457
- if (!key.Load (pkey, vchPubKey, fSkipCheck ))
458
- {
459
- strErr = " Error reading wallet database: CPrivKey corrupt" ;
460
- return false ;
461
- }
462
- if (!pwallet->GetOrCreateLegacyScriptPubKeyMan ()->LoadKey (key, vchPubKey))
463
- {
464
- strErr = " Error reading wallet database: LegacyScriptPubKeyMan::LoadKey failed" ;
465
- return false ;
466
- }
480
+ if (!LoadKey (pwallet, ssKey, ssValue, strErr)) return false ;
467
481
} else if (strType == DBKeys::MASTER_KEY) {
468
482
// Master encryption key is loaded into only the wallet and not any of the ScriptPubKeyMans.
469
483
unsigned int nID;
0 commit comments