@@ -45,6 +45,8 @@ const std::string TX{"tx"};
45
45
const std::string VERSION{" version" };
46
46
const std::string WALLETDESCRIPTOR{" walletdescriptor" };
47
47
const std::string WALLETDESCRIPTORCACHE{" walletdescriptorcache" };
48
+ const std::string WALLETDESCRIPTORCKEY{" walletdescriptorckey" };
49
+ const std::string WALLETDESCRIPTORKEY{" walletdescriptorkey" };
48
50
const std::string WATCHMETA{" watchmeta" };
49
51
const std::string WATCHS{" watchs" };
50
52
} // namespace DBKeys
@@ -202,6 +204,8 @@ class CWalletScanState {
202
204
std::map<OutputType, uint256> m_active_external_spks;
203
205
std::map<OutputType, uint256> m_active_internal_spks;
204
206
std::map<uint256, DescriptorCache> m_descriptor_caches;
207
+ std::map<std::pair<uint256, CKeyID>, CKey> m_descriptor_keys;
208
+ std::map<std::pair<uint256, CKeyID>, std::pair<CPubKey, std::vector<unsigned char >>> m_descriptor_crypt_keys;
205
209
206
210
CWalletScanState () {
207
211
}
@@ -467,6 +471,58 @@ ReadKeyValue(CWallet* pwallet, CDataStream& ssKey, CDataStream& ssValue,
467
471
} else {
468
472
wss.m_descriptor_caches [desc_id].CacheDerivedExtPubKey (key_exp_index, der_index, xpub);
469
473
}
474
+ } else if (strType == DBKeys::WALLETDESCRIPTORKEY) {
475
+ uint256 desc_id;
476
+ CPubKey pubkey;
477
+ ssKey >> desc_id;
478
+ ssKey >> pubkey;
479
+ if (!pubkey.IsValid ())
480
+ {
481
+ strErr = " Error reading wallet database: CPubKey corrupt" ;
482
+ return false ;
483
+ }
484
+ CKey key;
485
+ CPrivKey pkey;
486
+ uint256 hash;
487
+
488
+ wss.nKeys ++;
489
+ ssValue >> pkey;
490
+ ssValue >> hash;
491
+
492
+ // hash pubkey/privkey to accelerate wallet load
493
+ std::vector<unsigned char > to_hash;
494
+ to_hash.reserve (pubkey.size () + pkey.size ());
495
+ to_hash.insert (to_hash.end (), pubkey.begin (), pubkey.end ());
496
+ to_hash.insert (to_hash.end (), pkey.begin (), pkey.end ());
497
+
498
+ if (Hash (to_hash.begin (), to_hash.end ()) != hash)
499
+ {
500
+ strErr = " Error reading wallet database: CPubKey/CPrivKey corrupt" ;
501
+ return false ;
502
+ }
503
+
504
+ if (!key.Load (pkey, pubkey, true ))
505
+ {
506
+ strErr = " Error reading wallet database: CPrivKey corrupt" ;
507
+ return false ;
508
+ }
509
+ wss.m_descriptor_keys .insert (std::make_pair (std::make_pair (desc_id, pubkey.GetID ()), key));
510
+ } else if (strType == DBKeys::WALLETDESCRIPTORCKEY) {
511
+ uint256 desc_id;
512
+ CPubKey pubkey;
513
+ ssKey >> desc_id;
514
+ ssKey >> pubkey;
515
+ if (!pubkey.IsValid ())
516
+ {
517
+ strErr = " Error reading wallet database: CPubKey corrupt" ;
518
+ return false ;
519
+ }
520
+ std::vector<unsigned char > privkey;
521
+ ssValue >> privkey;
522
+ wss.nCKeys ++;
523
+
524
+ wss.m_descriptor_crypt_keys .insert (std::make_pair (std::make_pair (desc_id, pubkey.GetID ()), std::make_pair (pubkey, privkey)));
525
+ wss.fIsEncrypted = true ;
470
526
} else if (strType != DBKeys::BESTBLOCK && strType != DBKeys::BESTBLOCK_NOMERKLE &&
471
527
strType != DBKeys::MINVERSION && strType != DBKeys::ACENTRY &&
472
528
strType != DBKeys::VERSION && strType != DBKeys::SETTINGS) {
@@ -575,6 +631,16 @@ DBErrors WalletBatch::LoadWallet(CWallet* pwallet)
575
631
((DescriptorScriptPubKeyMan*)spk_man)->SetCache (desc_cache_pair.second );
576
632
}
577
633
634
+ // Set the descriptor keys
635
+ for (auto desc_key_pair : wss.m_descriptor_keys ) {
636
+ auto spk_man = pwallet->GetScriptPubKeyMan (desc_key_pair.first .first );
637
+ ((DescriptorScriptPubKeyMan*)spk_man)->AddKey (desc_key_pair.first .second , desc_key_pair.second );
638
+ }
639
+ for (auto desc_key_pair : wss.m_descriptor_crypt_keys ) {
640
+ auto spk_man = pwallet->GetScriptPubKeyMan (desc_key_pair.first .first );
641
+ ((DescriptorScriptPubKeyMan*)spk_man)->AddCryptedKey (desc_key_pair.first .second , desc_key_pair.second .first , desc_key_pair.second .second );
642
+ }
643
+
578
644
if (fNoncriticalErrors && result == DBErrors::LOAD_OK)
579
645
result = DBErrors::NONCRITICAL_ERROR;
580
646
0 commit comments