walletdb.cpp
1 // Copyright (c) 2009-2010 Satoshi Nakamoto 2 // Copyright (c) 2009-2022 The Bitcoin Core developers 3 // Distributed under the MIT software license, see the accompanying 4 // file COPYING or http://www.opensource.org/licenses/mit-license.php. 5 6 #if defined(HAVE_CONFIG_H) 7 #include <config/bitcoin-config.h> 8 #endif 9 10 #include <wallet/walletdb.h> 11 12 #include <common/system.h> 13 #include <key_io.h> 14 #include <protocol.h> 15 #include <script/script.h> 16 #include <serialize.h> 17 #include <sync.h> 18 #include <util/bip32.h> 19 #include <util/check.h> 20 #include <util/fs.h> 21 #include <util/time.h> 22 #include <util/translation.h> 23 #ifdef USE_BDB 24 #include <wallet/bdb.h> 25 #endif 26 #ifdef USE_SQLITE 27 #include <wallet/sqlite.h> 28 #endif 29 #include <wallet/wallet.h> 30 31 #include <atomic> 32 #include <optional> 33 #include <string> 34 35 namespace wallet { 36 namespace DBKeys { 37 const std::string ACENTRY{"acentry"}; 38 const std::string ACTIVEEXTERNALSPK{"activeexternalspk"}; 39 const std::string ACTIVEINTERNALSPK{"activeinternalspk"}; 40 const std::string BESTBLOCK_NOMERKLE{"bestblock_nomerkle"}; 41 const std::string BESTBLOCK{"bestblock"}; 42 const std::string CRYPTED_KEY{"ckey"}; 43 const std::string CSCRIPT{"cscript"}; 44 const std::string DEFAULTKEY{"defaultkey"}; 45 const std::string DESTDATA{"destdata"}; 46 const std::string FLAGS{"flags"}; 47 const std::string HDCHAIN{"hdchain"}; 48 const std::string KEYMETA{"keymeta"}; 49 const std::string KEY{"key"}; 50 const std::string LOCKED_UTXO{"lockedutxo"}; 51 const std::string MASTER_KEY{"mkey"}; 52 const std::string MINVERSION{"minversion"}; 53 const std::string NAME{"name"}; 54 const std::string OLD_KEY{"wkey"}; 55 const std::string ORDERPOSNEXT{"orderposnext"}; 56 const std::string POOL{"pool"}; 57 const std::string PURPOSE{"purpose"}; 58 const std::string SETTINGS{"settings"}; 59 const std::string TX{"tx"}; 60 const std::string VERSION{"version"}; 61 const std::string WALLETDESCRIPTOR{"walletdescriptor"}; 62 const std::string WALLETDESCRIPTORCACHE{"walletdescriptorcache"}; 63 const std::string WALLETDESCRIPTORLHCACHE{"walletdescriptorlhcache"}; 64 const std::string WALLETDESCRIPTORCKEY{"walletdescriptorckey"}; 65 const std::string WALLETDESCRIPTORKEY{"walletdescriptorkey"}; 66 const std::string WATCHMETA{"watchmeta"}; 67 const std::string WATCHS{"watchs"}; 68 const std::unordered_set<std::string> LEGACY_TYPES{CRYPTED_KEY, CSCRIPT, DEFAULTKEY, HDCHAIN, KEYMETA, KEY, OLD_KEY, POOL, WATCHMETA, WATCHS}; 69 } // namespace DBKeys 70 71 // 72 // WalletBatch 73 // 74 75 bool WalletBatch::WriteName(const std::string& strAddress, const std::string& strName) 76 { 77 return WriteIC(std::make_pair(DBKeys::NAME, strAddress), strName); 78 } 79 80 bool WalletBatch::EraseName(const std::string& strAddress) 81 { 82 // This should only be used for sending addresses, never for receiving addresses, 83 // receiving addresses must always have an address book entry if they're not change return. 84 return EraseIC(std::make_pair(DBKeys::NAME, strAddress)); 85 } 86 87 bool WalletBatch::WritePurpose(const std::string& strAddress, const std::string& strPurpose) 88 { 89 return WriteIC(std::make_pair(DBKeys::PURPOSE, strAddress), strPurpose); 90 } 91 92 bool WalletBatch::ErasePurpose(const std::string& strAddress) 93 { 94 return EraseIC(std::make_pair(DBKeys::PURPOSE, strAddress)); 95 } 96 97 bool WalletBatch::WriteTx(const CWalletTx& wtx) 98 { 99 return WriteIC(std::make_pair(DBKeys::TX, wtx.GetHash()), wtx); 100 } 101 102 bool WalletBatch::EraseTx(uint256 hash) 103 { 104 return EraseIC(std::make_pair(DBKeys::TX, hash)); 105 } 106 107 bool WalletBatch::WriteKeyMetadata(const CKeyMetadata& meta, const CPubKey& pubkey, const bool overwrite) 108 { 109 return WriteIC(std::make_pair(DBKeys::KEYMETA, pubkey), meta, overwrite); 110 } 111 112 bool WalletBatch::WriteKey(const CPubKey& vchPubKey, const CPrivKey& vchPrivKey, const CKeyMetadata& keyMeta) 113 { 114 if (!WriteKeyMetadata(keyMeta, vchPubKey, false)) { 115 return false; 116 } 117 118 // hash pubkey/privkey to accelerate wallet load 119 std::vector<unsigned char> vchKey; 120 vchKey.reserve(vchPubKey.size() + vchPrivKey.size()); 121 vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end()); 122 vchKey.insert(vchKey.end(), vchPrivKey.begin(), vchPrivKey.end()); 123 124 return WriteIC(std::make_pair(DBKeys::KEY, vchPubKey), std::make_pair(vchPrivKey, Hash(vchKey)), false); 125 } 126 127 bool WalletBatch::WriteCryptedKey(const CPubKey& vchPubKey, 128 const std::vector<unsigned char>& vchCryptedSecret, 129 const CKeyMetadata &keyMeta) 130 { 131 if (!WriteKeyMetadata(keyMeta, vchPubKey, true)) { 132 return false; 133 } 134 135 // Compute a checksum of the encrypted key 136 uint256 checksum = Hash(vchCryptedSecret); 137 138 const auto key = std::make_pair(DBKeys::CRYPTED_KEY, vchPubKey); 139 if (!WriteIC(key, std::make_pair(vchCryptedSecret, checksum), false)) { 140 // It may already exist, so try writing just the checksum 141 std::vector<unsigned char> val; 142 if (!m_batch->Read(key, val)) { 143 return false; 144 } 145 if (!WriteIC(key, std::make_pair(val, checksum), true)) { 146 return false; 147 } 148 } 149 EraseIC(std::make_pair(DBKeys::KEY, vchPubKey)); 150 return true; 151 } 152 153 bool WalletBatch::WriteMasterKey(unsigned int nID, const CMasterKey& kMasterKey) 154 { 155 return WriteIC(std::make_pair(DBKeys::MASTER_KEY, nID), kMasterKey, true); 156 } 157 158 bool WalletBatch::WriteCScript(const uint160& hash, const CScript& redeemScript) 159 { 160 return WriteIC(std::make_pair(DBKeys::CSCRIPT, hash), redeemScript, false); 161 } 162 163 bool WalletBatch::WriteWatchOnly(const CScript &dest, const CKeyMetadata& keyMeta) 164 { 165 if (!WriteIC(std::make_pair(DBKeys::WATCHMETA, dest), keyMeta)) { 166 return false; 167 } 168 return WriteIC(std::make_pair(DBKeys::WATCHS, dest), uint8_t{'1'}); 169 } 170 171 bool WalletBatch::EraseWatchOnly(const CScript &dest) 172 { 173 if (!EraseIC(std::make_pair(DBKeys::WATCHMETA, dest))) { 174 return false; 175 } 176 return EraseIC(std::make_pair(DBKeys::WATCHS, dest)); 177 } 178 179 bool WalletBatch::WriteBestBlock(const CBlockLocator& locator) 180 { 181 WriteIC(DBKeys::BESTBLOCK, CBlockLocator()); // Write empty block locator so versions that require a merkle branch automatically rescan 182 return WriteIC(DBKeys::BESTBLOCK_NOMERKLE, locator); 183 } 184 185 bool WalletBatch::ReadBestBlock(CBlockLocator& locator) 186 { 187 if (m_batch->Read(DBKeys::BESTBLOCK, locator) && !locator.vHave.empty()) return true; 188 return m_batch->Read(DBKeys::BESTBLOCK_NOMERKLE, locator); 189 } 190 191 bool WalletBatch::WriteOrderPosNext(int64_t nOrderPosNext) 192 { 193 return WriteIC(DBKeys::ORDERPOSNEXT, nOrderPosNext); 194 } 195 196 bool WalletBatch::ReadPool(int64_t nPool, CKeyPool& keypool) 197 { 198 return m_batch->Read(std::make_pair(DBKeys::POOL, nPool), keypool); 199 } 200 201 bool WalletBatch::WritePool(int64_t nPool, const CKeyPool& keypool) 202 { 203 return WriteIC(std::make_pair(DBKeys::POOL, nPool), keypool); 204 } 205 206 bool WalletBatch::ErasePool(int64_t nPool) 207 { 208 return EraseIC(std::make_pair(DBKeys::POOL, nPool)); 209 } 210 211 bool WalletBatch::WriteMinVersion(int nVersion) 212 { 213 return WriteIC(DBKeys::MINVERSION, nVersion); 214 } 215 216 bool WalletBatch::WriteActiveScriptPubKeyMan(uint8_t type, const uint256& id, bool internal) 217 { 218 std::string key = internal ? DBKeys::ACTIVEINTERNALSPK : DBKeys::ACTIVEEXTERNALSPK; 219 return WriteIC(make_pair(key, type), id); 220 } 221 222 bool WalletBatch::EraseActiveScriptPubKeyMan(uint8_t type, bool internal) 223 { 224 const std::string key{internal ? DBKeys::ACTIVEINTERNALSPK : DBKeys::ACTIVEEXTERNALSPK}; 225 return EraseIC(make_pair(key, type)); 226 } 227 228 bool WalletBatch::WriteDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const CPrivKey& privkey) 229 { 230 // hash pubkey/privkey to accelerate wallet load 231 std::vector<unsigned char> key; 232 key.reserve(pubkey.size() + privkey.size()); 233 key.insert(key.end(), pubkey.begin(), pubkey.end()); 234 key.insert(key.end(), privkey.begin(), privkey.end()); 235 236 return WriteIC(std::make_pair(DBKeys::WALLETDESCRIPTORKEY, std::make_pair(desc_id, pubkey)), std::make_pair(privkey, Hash(key)), false); 237 } 238 239 bool WalletBatch::WriteCryptedDescriptorKey(const uint256& desc_id, const CPubKey& pubkey, const std::vector<unsigned char>& secret) 240 { 241 if (!WriteIC(std::make_pair(DBKeys::WALLETDESCRIPTORCKEY, std::make_pair(desc_id, pubkey)), secret, false)) { 242 return false; 243 } 244 EraseIC(std::make_pair(DBKeys::WALLETDESCRIPTORKEY, std::make_pair(desc_id, pubkey))); 245 return true; 246 } 247 248 bool WalletBatch::WriteDescriptor(const uint256& desc_id, const WalletDescriptor& descriptor) 249 { 250 return WriteIC(make_pair(DBKeys::WALLETDESCRIPTOR, desc_id), descriptor); 251 } 252 253 bool WalletBatch::WriteDescriptorDerivedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index, uint32_t der_index) 254 { 255 std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE); 256 xpub.Encode(ser_xpub.data()); 257 return WriteIC(std::make_pair(std::make_pair(DBKeys::WALLETDESCRIPTORCACHE, desc_id), std::make_pair(key_exp_index, der_index)), ser_xpub); 258 } 259 260 bool WalletBatch::WriteDescriptorParentCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index) 261 { 262 std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE); 263 xpub.Encode(ser_xpub.data()); 264 return WriteIC(std::make_pair(std::make_pair(DBKeys::WALLETDESCRIPTORCACHE, desc_id), key_exp_index), ser_xpub); 265 } 266 267 bool WalletBatch::WriteDescriptorLastHardenedCache(const CExtPubKey& xpub, const uint256& desc_id, uint32_t key_exp_index) 268 { 269 std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE); 270 xpub.Encode(ser_xpub.data()); 271 return WriteIC(std::make_pair(std::make_pair(DBKeys::WALLETDESCRIPTORLHCACHE, desc_id), key_exp_index), ser_xpub); 272 } 273 274 bool WalletBatch::WriteDescriptorCacheItems(const uint256& desc_id, const DescriptorCache& cache) 275 { 276 for (const auto& parent_xpub_pair : cache.GetCachedParentExtPubKeys()) { 277 if (!WriteDescriptorParentCache(parent_xpub_pair.second, desc_id, parent_xpub_pair.first)) { 278 return false; 279 } 280 } 281 for (const auto& derived_xpub_map_pair : cache.GetCachedDerivedExtPubKeys()) { 282 for (const auto& derived_xpub_pair : derived_xpub_map_pair.second) { 283 if (!WriteDescriptorDerivedCache(derived_xpub_pair.second, desc_id, derived_xpub_map_pair.first, derived_xpub_pair.first)) { 284 return false; 285 } 286 } 287 } 288 for (const auto& lh_xpub_pair : cache.GetCachedLastHardenedExtPubKeys()) { 289 if (!WriteDescriptorLastHardenedCache(lh_xpub_pair.second, desc_id, lh_xpub_pair.first)) { 290 return false; 291 } 292 } 293 return true; 294 } 295 296 bool WalletBatch::WriteLockedUTXO(const COutPoint& output) 297 { 298 return WriteIC(std::make_pair(DBKeys::LOCKED_UTXO, std::make_pair(output.hash, output.n)), uint8_t{'1'}); 299 } 300 301 bool WalletBatch::EraseLockedUTXO(const COutPoint& output) 302 { 303 return EraseIC(std::make_pair(DBKeys::LOCKED_UTXO, std::make_pair(output.hash, output.n))); 304 } 305 306 bool LoadKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::string& strErr) 307 { 308 LOCK(pwallet->cs_wallet); 309 try { 310 CPubKey vchPubKey; 311 ssKey >> vchPubKey; 312 if (!vchPubKey.IsValid()) 313 { 314 strErr = "Error reading wallet database: CPubKey corrupt"; 315 return false; 316 } 317 CKey key; 318 CPrivKey pkey; 319 uint256 hash; 320 321 ssValue >> pkey; 322 323 // Old wallets store keys as DBKeys::KEY [pubkey] => [privkey] 324 // ... which was slow for wallets with lots of keys, because the public key is re-derived from the private key 325 // using EC operations as a checksum. 326 // Newer wallets store keys as DBKeys::KEY [pubkey] => [privkey][hash(pubkey,privkey)], which is much faster while 327 // remaining backwards-compatible. 328 try 329 { 330 ssValue >> hash; 331 } 332 catch (const std::ios_base::failure&) {} 333 334 bool fSkipCheck = false; 335 336 if (!hash.IsNull()) 337 { 338 // hash pubkey/privkey to accelerate wallet load 339 std::vector<unsigned char> vchKey; 340 vchKey.reserve(vchPubKey.size() + pkey.size()); 341 vchKey.insert(vchKey.end(), vchPubKey.begin(), vchPubKey.end()); 342 vchKey.insert(vchKey.end(), pkey.begin(), pkey.end()); 343 344 if (Hash(vchKey) != hash) 345 { 346 strErr = "Error reading wallet database: CPubKey/CPrivKey corrupt"; 347 return false; 348 } 349 350 fSkipCheck = true; 351 } 352 353 if (!key.Load(pkey, vchPubKey, fSkipCheck)) 354 { 355 strErr = "Error reading wallet database: CPrivKey corrupt"; 356 return false; 357 } 358 if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKey(key, vchPubKey)) 359 { 360 strErr = "Error reading wallet database: LegacyScriptPubKeyMan::LoadKey failed"; 361 return false; 362 } 363 } catch (const std::exception& e) { 364 if (strErr.empty()) { 365 strErr = e.what(); 366 } 367 return false; 368 } 369 return true; 370 } 371 372 bool LoadCryptedKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::string& strErr) 373 { 374 LOCK(pwallet->cs_wallet); 375 try { 376 CPubKey vchPubKey; 377 ssKey >> vchPubKey; 378 if (!vchPubKey.IsValid()) 379 { 380 strErr = "Error reading wallet database: CPubKey corrupt"; 381 return false; 382 } 383 std::vector<unsigned char> vchPrivKey; 384 ssValue >> vchPrivKey; 385 386 // Get the checksum and check it 387 bool checksum_valid = false; 388 if (!ssValue.eof()) { 389 uint256 checksum; 390 ssValue >> checksum; 391 if (!(checksum_valid = Hash(vchPrivKey) == checksum)) { 392 strErr = "Error reading wallet database: Encrypted key corrupt"; 393 return false; 394 } 395 } 396 397 if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadCryptedKey(vchPubKey, vchPrivKey, checksum_valid)) 398 { 399 strErr = "Error reading wallet database: LegacyScriptPubKeyMan::LoadCryptedKey failed"; 400 return false; 401 } 402 } catch (const std::exception& e) { 403 if (strErr.empty()) { 404 strErr = e.what(); 405 } 406 return false; 407 } 408 return true; 409 } 410 411 bool LoadEncryptionKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::string& strErr) 412 { 413 LOCK(pwallet->cs_wallet); 414 try { 415 // Master encryption key is loaded into only the wallet and not any of the ScriptPubKeyMans. 416 unsigned int nID; 417 ssKey >> nID; 418 CMasterKey kMasterKey; 419 ssValue >> kMasterKey; 420 if(pwallet->mapMasterKeys.count(nID) != 0) 421 { 422 strErr = strprintf("Error reading wallet database: duplicate CMasterKey id %u", nID); 423 return false; 424 } 425 pwallet->mapMasterKeys[nID] = kMasterKey; 426 if (pwallet->nMasterKeyMaxID < nID) 427 pwallet->nMasterKeyMaxID = nID; 428 429 } catch (const std::exception& e) { 430 if (strErr.empty()) { 431 strErr = e.what(); 432 } 433 return false; 434 } 435 return true; 436 } 437 438 bool LoadHDChain(CWallet* pwallet, DataStream& ssValue, std::string& strErr) 439 { 440 LOCK(pwallet->cs_wallet); 441 try { 442 CHDChain chain; 443 ssValue >> chain; 444 pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadHDChain(chain); 445 } catch (const std::exception& e) { 446 if (strErr.empty()) { 447 strErr = e.what(); 448 } 449 return false; 450 } 451 return true; 452 } 453 454 static DBErrors LoadMinVersion(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) 455 { 456 AssertLockHeld(pwallet->cs_wallet); 457 int nMinVersion = 0; 458 if (batch.Read(DBKeys::MINVERSION, nMinVersion)) { 459 if (nMinVersion > FEATURE_LATEST) 460 return DBErrors::TOO_NEW; 461 pwallet->LoadMinVersion(nMinVersion); 462 } 463 return DBErrors::LOAD_OK; 464 } 465 466 static DBErrors LoadWalletFlags(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) 467 { 468 AssertLockHeld(pwallet->cs_wallet); 469 uint64_t flags; 470 if (batch.Read(DBKeys::FLAGS, flags)) { 471 if (!pwallet->LoadWalletFlags(flags)) { 472 pwallet->WalletLogPrintf("Error reading wallet database: Unknown non-tolerable wallet flags found\n"); 473 return DBErrors::TOO_NEW; 474 } 475 } 476 return DBErrors::LOAD_OK; 477 } 478 479 struct LoadResult 480 { 481 DBErrors m_result{DBErrors::LOAD_OK}; 482 int m_records{0}; 483 }; 484 485 using LoadFunc = std::function<DBErrors(CWallet* pwallet, DataStream& key, DataStream& value, std::string& err)>; 486 static LoadResult LoadRecords(CWallet* pwallet, DatabaseBatch& batch, const std::string& key, DataStream& prefix, LoadFunc load_func) 487 { 488 LoadResult result; 489 DataStream ssKey; 490 DataStream ssValue{}; 491 492 Assume(!prefix.empty()); 493 std::unique_ptr<DatabaseCursor> cursor = batch.GetNewPrefixCursor(prefix); 494 if (!cursor) { 495 pwallet->WalletLogPrintf("Error getting database cursor for '%s' records\n", key); 496 result.m_result = DBErrors::CORRUPT; 497 return result; 498 } 499 500 while (true) { 501 DatabaseCursor::Status status = cursor->Next(ssKey, ssValue); 502 if (status == DatabaseCursor::Status::DONE) { 503 break; 504 } else if (status == DatabaseCursor::Status::FAIL) { 505 pwallet->WalletLogPrintf("Error reading next '%s' record for wallet database\n", key); 506 result.m_result = DBErrors::CORRUPT; 507 return result; 508 } 509 std::string type; 510 ssKey >> type; 511 assert(type == key); 512 std::string error; 513 DBErrors record_res = load_func(pwallet, ssKey, ssValue, error); 514 if (record_res != DBErrors::LOAD_OK) { 515 pwallet->WalletLogPrintf("%s\n", error); 516 } 517 result.m_result = std::max(result.m_result, record_res); 518 ++result.m_records; 519 } 520 return result; 521 } 522 523 static LoadResult LoadRecords(CWallet* pwallet, DatabaseBatch& batch, const std::string& key, LoadFunc load_func) 524 { 525 DataStream prefix; 526 prefix << key; 527 return LoadRecords(pwallet, batch, key, prefix, load_func); 528 } 529 530 static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch, int last_client) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) 531 { 532 AssertLockHeld(pwallet->cs_wallet); 533 DBErrors result = DBErrors::LOAD_OK; 534 535 // Make sure descriptor wallets don't have any legacy records 536 if (pwallet->IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) { 537 for (const auto& type : DBKeys::LEGACY_TYPES) { 538 DataStream key; 539 DataStream value{}; 540 541 DataStream prefix; 542 prefix << type; 543 std::unique_ptr<DatabaseCursor> cursor = batch.GetNewPrefixCursor(prefix); 544 if (!cursor) { 545 pwallet->WalletLogPrintf("Error getting database cursor for '%s' records\n", type); 546 return DBErrors::CORRUPT; 547 } 548 549 DatabaseCursor::Status status = cursor->Next(key, value); 550 if (status != DatabaseCursor::Status::DONE) { 551 pwallet->WalletLogPrintf("Error: Unexpected legacy entry found in descriptor wallet %s. The wallet might have been tampered with or created with malicious intent.\n", pwallet->GetName()); 552 return DBErrors::UNEXPECTED_LEGACY_ENTRY; 553 } 554 } 555 556 return DBErrors::LOAD_OK; 557 } 558 559 // Load HD Chain 560 // Note: There should only be one HDCHAIN record with no data following the type 561 LoadResult hd_chain_res = LoadRecords(pwallet, batch, DBKeys::HDCHAIN, 562 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) { 563 return LoadHDChain(pwallet, value, err) ? DBErrors:: LOAD_OK : DBErrors::CORRUPT; 564 }); 565 result = std::max(result, hd_chain_res.m_result); 566 567 // Load unencrypted keys 568 LoadResult key_res = LoadRecords(pwallet, batch, DBKeys::KEY, 569 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) { 570 return LoadKey(pwallet, key, value, err) ? DBErrors::LOAD_OK : DBErrors::CORRUPT; 571 }); 572 result = std::max(result, key_res.m_result); 573 574 // Load encrypted keys 575 LoadResult ckey_res = LoadRecords(pwallet, batch, DBKeys::CRYPTED_KEY, 576 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) { 577 return LoadCryptedKey(pwallet, key, value, err) ? DBErrors::LOAD_OK : DBErrors::CORRUPT; 578 }); 579 result = std::max(result, ckey_res.m_result); 580 581 // Load scripts 582 LoadResult script_res = LoadRecords(pwallet, batch, DBKeys::CSCRIPT, 583 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& strErr) { 584 uint160 hash; 585 key >> hash; 586 CScript script; 587 value >> script; 588 if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadCScript(script)) 589 { 590 strErr = "Error reading wallet database: LegacyScriptPubKeyMan::LoadCScript failed"; 591 return DBErrors::NONCRITICAL_ERROR; 592 } 593 return DBErrors::LOAD_OK; 594 }); 595 result = std::max(result, script_res.m_result); 596 597 // Check whether rewrite is needed 598 if (ckey_res.m_records > 0) { 599 // Rewrite encrypted wallets of versions 0.4.0 and 0.5.0rc: 600 if (last_client == 40000 || last_client == 50000) result = std::max(result, DBErrors::NEED_REWRITE); 601 } 602 603 // Load keymeta 604 std::map<uint160, CHDChain> hd_chains; 605 LoadResult keymeta_res = LoadRecords(pwallet, batch, DBKeys::KEYMETA, 606 [&hd_chains] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& strErr) { 607 CPubKey vchPubKey; 608 key >> vchPubKey; 609 CKeyMetadata keyMeta; 610 value >> keyMeta; 611 pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKeyMetadata(vchPubKey.GetID(), keyMeta); 612 613 // Extract some CHDChain info from this metadata if it has any 614 if (keyMeta.nVersion >= CKeyMetadata::VERSION_WITH_HDDATA && !keyMeta.hd_seed_id.IsNull() && keyMeta.hdKeypath.size() > 0) { 615 // Get the path from the key origin or from the path string 616 // Not applicable when path is "s" or "m" as those indicate a seed 617 // See https://github.com/bitcoin/bitcoin/pull/12924 618 bool internal = false; 619 uint32_t index = 0; 620 if (keyMeta.hdKeypath != "s" && keyMeta.hdKeypath != "m") { 621 std::vector<uint32_t> path; 622 if (keyMeta.has_key_origin) { 623 // We have a key origin, so pull it from its path vector 624 path = keyMeta.key_origin.path; 625 } else { 626 // No key origin, have to parse the string 627 if (!ParseHDKeypath(keyMeta.hdKeypath, path)) { 628 strErr = "Error reading wallet database: keymeta with invalid HD keypath"; 629 return DBErrors::NONCRITICAL_ERROR; 630 } 631 } 632 633 // Extract the index and internal from the path 634 // Path string is m/0'/k'/i' 635 // Path vector is [0', k', i'] (but as ints OR'd with the hardened bit 636 // k == 0 for external, 1 for internal. i is the index 637 if (path.size() != 3) { 638 strErr = "Error reading wallet database: keymeta found with unexpected path"; 639 return DBErrors::NONCRITICAL_ERROR; 640 } 641 if (path[0] != 0x80000000) { 642 strErr = strprintf("Unexpected path index of 0x%08x (expected 0x80000000) for the element at index 0", path[0]); 643 return DBErrors::NONCRITICAL_ERROR; 644 } 645 if (path[1] != 0x80000000 && path[1] != (1 | 0x80000000)) { 646 strErr = strprintf("Unexpected path index of 0x%08x (expected 0x80000000 or 0x80000001) for the element at index 1", path[1]); 647 return DBErrors::NONCRITICAL_ERROR; 648 } 649 if ((path[2] & 0x80000000) == 0) { 650 strErr = strprintf("Unexpected path index of 0x%08x (expected to be greater than or equal to 0x80000000)", path[2]); 651 return DBErrors::NONCRITICAL_ERROR; 652 } 653 internal = path[1] == (1 | 0x80000000); 654 index = path[2] & ~0x80000000; 655 } 656 657 // Insert a new CHDChain, or get the one that already exists 658 auto [ins, inserted] = hd_chains.emplace(keyMeta.hd_seed_id, CHDChain()); 659 CHDChain& chain = ins->second; 660 if (inserted) { 661 // For new chains, we want to default to VERSION_HD_BASE until we see an internal 662 chain.nVersion = CHDChain::VERSION_HD_BASE; 663 chain.seed_id = keyMeta.hd_seed_id; 664 } 665 if (internal) { 666 chain.nVersion = CHDChain::VERSION_HD_CHAIN_SPLIT; 667 chain.nInternalChainCounter = std::max(chain.nInternalChainCounter, index + 1); 668 } else { 669 chain.nExternalChainCounter = std::max(chain.nExternalChainCounter, index + 1); 670 } 671 } 672 return DBErrors::LOAD_OK; 673 }); 674 result = std::max(result, keymeta_res.m_result); 675 676 // Set inactive chains 677 if (!hd_chains.empty()) { 678 LegacyScriptPubKeyMan* legacy_spkm = pwallet->GetLegacyScriptPubKeyMan(); 679 if (legacy_spkm) { 680 for (const auto& [hd_seed_id, chain] : hd_chains) { 681 if (hd_seed_id != legacy_spkm->GetHDChain().seed_id) { 682 legacy_spkm->AddInactiveHDChain(chain); 683 } 684 } 685 } else { 686 pwallet->WalletLogPrintf("Inactive HD Chains found but no Legacy ScriptPubKeyMan\n"); 687 result = DBErrors::CORRUPT; 688 } 689 } 690 691 // Load watchonly scripts 692 LoadResult watch_script_res = LoadRecords(pwallet, batch, DBKeys::WATCHS, 693 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) { 694 CScript script; 695 key >> script; 696 uint8_t fYes; 697 value >> fYes; 698 if (fYes == '1') { 699 pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadWatchOnly(script); 700 } 701 return DBErrors::LOAD_OK; 702 }); 703 result = std::max(result, watch_script_res.m_result); 704 705 // Load watchonly meta 706 LoadResult watch_meta_res = LoadRecords(pwallet, batch, DBKeys::WATCHMETA, 707 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) { 708 CScript script; 709 key >> script; 710 CKeyMetadata keyMeta; 711 value >> keyMeta; 712 pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadScriptMetadata(CScriptID(script), keyMeta); 713 return DBErrors::LOAD_OK; 714 }); 715 result = std::max(result, watch_meta_res.m_result); 716 717 // Load keypool 718 LoadResult pool_res = LoadRecords(pwallet, batch, DBKeys::POOL, 719 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) { 720 int64_t nIndex; 721 key >> nIndex; 722 CKeyPool keypool; 723 value >> keypool; 724 pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKeyPool(nIndex, keypool); 725 return DBErrors::LOAD_OK; 726 }); 727 result = std::max(result, pool_res.m_result); 728 729 // Deal with old "wkey" and "defaultkey" records. 730 // These are not actually loaded, but we need to check for them 731 732 // We don't want or need the default key, but if there is one set, 733 // we want to make sure that it is valid so that we can detect corruption 734 // Note: There should only be one DEFAULTKEY with nothing trailing the type 735 LoadResult default_key_res = LoadRecords(pwallet, batch, DBKeys::DEFAULTKEY, 736 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) { 737 CPubKey default_pubkey; 738 try { 739 value >> default_pubkey; 740 } catch (const std::exception& e) { 741 err = e.what(); 742 return DBErrors::CORRUPT; 743 } 744 if (!default_pubkey.IsValid()) { 745 err = "Error reading wallet database: Default Key corrupt"; 746 return DBErrors::CORRUPT; 747 } 748 return DBErrors::LOAD_OK; 749 }); 750 result = std::max(result, default_key_res.m_result); 751 752 // "wkey" records are unsupported, if we see any, throw an error 753 LoadResult wkey_res = LoadRecords(pwallet, batch, DBKeys::OLD_KEY, 754 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) { 755 err = "Found unsupported 'wkey' record, try loading with version 0.18"; 756 return DBErrors::LOAD_FAIL; 757 }); 758 result = std::max(result, wkey_res.m_result); 759 760 if (result <= DBErrors::NONCRITICAL_ERROR) { 761 // Only do logging and time first key update if there were no critical errors 762 pwallet->WalletLogPrintf("Legacy Wallet Keys: %u plaintext, %u encrypted, %u w/ metadata, %u total.\n", 763 key_res.m_records, ckey_res.m_records, keymeta_res.m_records, key_res.m_records + ckey_res.m_records); 764 765 // nTimeFirstKey is only reliable if all keys have metadata 766 if (pwallet->IsLegacy() && (key_res.m_records + ckey_res.m_records + watch_script_res.m_records) != (keymeta_res.m_records + watch_meta_res.m_records)) { 767 auto spk_man = pwallet->GetOrCreateLegacyScriptPubKeyMan(); 768 if (spk_man) { 769 LOCK(spk_man->cs_KeyStore); 770 spk_man->UpdateTimeFirstKey(1); 771 } 772 } 773 } 774 775 return result; 776 } 777 778 template<typename... Args> 779 static DataStream PrefixStream(const Args&... args) 780 { 781 DataStream prefix; 782 SerializeMany(prefix, args...); 783 return prefix; 784 } 785 786 static DBErrors LoadDescriptorWalletRecords(CWallet* pwallet, DatabaseBatch& batch, int last_client) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) 787 { 788 AssertLockHeld(pwallet->cs_wallet); 789 790 // Load descriptor record 791 int num_keys = 0; 792 int num_ckeys= 0; 793 LoadResult desc_res = LoadRecords(pwallet, batch, DBKeys::WALLETDESCRIPTOR, 794 [&batch, &num_keys, &num_ckeys, &last_client] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& strErr) { 795 DBErrors result = DBErrors::LOAD_OK; 796 797 uint256 id; 798 key >> id; 799 WalletDescriptor desc; 800 try { 801 value >> desc; 802 } catch (const std::ios_base::failure& e) { 803 strErr = strprintf("Error: Unrecognized descriptor found in wallet %s. ", pwallet->GetName()); 804 strErr += (last_client > CLIENT_VERSION) ? "The wallet might had been created on a newer version. " : 805 "The database might be corrupted or the software version is not compatible with one of your wallet descriptors. "; 806 strErr += "Please try running the latest software version"; 807 // Also include error details 808 strErr = strprintf("%s\nDetails: %s", strErr, e.what()); 809 return DBErrors::UNKNOWN_DESCRIPTOR; 810 } 811 DescriptorScriptPubKeyMan& spkm = pwallet->LoadDescriptorScriptPubKeyMan(id, desc); 812 813 // Prior to doing anything with this spkm, verify ID compatibility 814 if (id != spkm.GetID()) { 815 strErr = "The descriptor ID calculated by the wallet differs from the one in DB"; 816 return DBErrors::CORRUPT; 817 } 818 819 DescriptorCache cache; 820 821 // Get key cache for this descriptor 822 DataStream prefix = PrefixStream(DBKeys::WALLETDESCRIPTORCACHE, id); 823 LoadResult key_cache_res = LoadRecords(pwallet, batch, DBKeys::WALLETDESCRIPTORCACHE, prefix, 824 [&id, &cache] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) { 825 bool parent = true; 826 uint256 desc_id; 827 uint32_t key_exp_index; 828 uint32_t der_index; 829 key >> desc_id; 830 assert(desc_id == id); 831 key >> key_exp_index; 832 833 // if the der_index exists, it's a derived xpub 834 try 835 { 836 key >> der_index; 837 parent = false; 838 } 839 catch (...) {} 840 841 std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE); 842 value >> ser_xpub; 843 CExtPubKey xpub; 844 xpub.Decode(ser_xpub.data()); 845 if (parent) { 846 cache.CacheParentExtPubKey(key_exp_index, xpub); 847 } else { 848 cache.CacheDerivedExtPubKey(key_exp_index, der_index, xpub); 849 } 850 return DBErrors::LOAD_OK; 851 }); 852 result = std::max(result, key_cache_res.m_result); 853 854 // Get last hardened cache for this descriptor 855 prefix = PrefixStream(DBKeys::WALLETDESCRIPTORLHCACHE, id); 856 LoadResult lh_cache_res = LoadRecords(pwallet, batch, DBKeys::WALLETDESCRIPTORLHCACHE, prefix, 857 [&id, &cache] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) { 858 uint256 desc_id; 859 uint32_t key_exp_index; 860 key >> desc_id; 861 assert(desc_id == id); 862 key >> key_exp_index; 863 864 std::vector<unsigned char> ser_xpub(BIP32_EXTKEY_SIZE); 865 value >> ser_xpub; 866 CExtPubKey xpub; 867 xpub.Decode(ser_xpub.data()); 868 cache.CacheLastHardenedExtPubKey(key_exp_index, xpub); 869 return DBErrors::LOAD_OK; 870 }); 871 result = std::max(result, lh_cache_res.m_result); 872 873 // Set the cache for this descriptor 874 auto spk_man = (DescriptorScriptPubKeyMan*)pwallet->GetScriptPubKeyMan(id); 875 assert(spk_man); 876 spk_man->SetCache(cache); 877 878 // Get unencrypted keys 879 prefix = PrefixStream(DBKeys::WALLETDESCRIPTORKEY, id); 880 LoadResult key_res = LoadRecords(pwallet, batch, DBKeys::WALLETDESCRIPTORKEY, prefix, 881 [&id, &spk_man] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& strErr) { 882 uint256 desc_id; 883 CPubKey pubkey; 884 key >> desc_id; 885 assert(desc_id == id); 886 key >> pubkey; 887 if (!pubkey.IsValid()) 888 { 889 strErr = "Error reading wallet database: descriptor unencrypted key CPubKey corrupt"; 890 return DBErrors::CORRUPT; 891 } 892 CKey privkey; 893 CPrivKey pkey; 894 uint256 hash; 895 896 value >> pkey; 897 value >> hash; 898 899 // hash pubkey/privkey to accelerate wallet load 900 std::vector<unsigned char> to_hash; 901 to_hash.reserve(pubkey.size() + pkey.size()); 902 to_hash.insert(to_hash.end(), pubkey.begin(), pubkey.end()); 903 to_hash.insert(to_hash.end(), pkey.begin(), pkey.end()); 904 905 if (Hash(to_hash) != hash) 906 { 907 strErr = "Error reading wallet database: descriptor unencrypted key CPubKey/CPrivKey corrupt"; 908 return DBErrors::CORRUPT; 909 } 910 911 if (!privkey.Load(pkey, pubkey, true)) 912 { 913 strErr = "Error reading wallet database: descriptor unencrypted key CPrivKey corrupt"; 914 return DBErrors::CORRUPT; 915 } 916 spk_man->AddKey(pubkey.GetID(), privkey); 917 return DBErrors::LOAD_OK; 918 }); 919 result = std::max(result, key_res.m_result); 920 num_keys = key_res.m_records; 921 922 // Get encrypted keys 923 prefix = PrefixStream(DBKeys::WALLETDESCRIPTORCKEY, id); 924 LoadResult ckey_res = LoadRecords(pwallet, batch, DBKeys::WALLETDESCRIPTORCKEY, prefix, 925 [&id, &spk_man] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) { 926 uint256 desc_id; 927 CPubKey pubkey; 928 key >> desc_id; 929 assert(desc_id == id); 930 key >> pubkey; 931 if (!pubkey.IsValid()) 932 { 933 err = "Error reading wallet database: descriptor encrypted key CPubKey corrupt"; 934 return DBErrors::CORRUPT; 935 } 936 std::vector<unsigned char> privkey; 937 value >> privkey; 938 939 spk_man->AddCryptedKey(pubkey.GetID(), pubkey, privkey); 940 return DBErrors::LOAD_OK; 941 }); 942 result = std::max(result, ckey_res.m_result); 943 num_ckeys = ckey_res.m_records; 944 945 return result; 946 }); 947 948 if (desc_res.m_result <= DBErrors::NONCRITICAL_ERROR) { 949 // Only log if there are no critical errors 950 pwallet->WalletLogPrintf("Descriptors: %u, Descriptor Keys: %u plaintext, %u encrypted, %u total.\n", 951 desc_res.m_records, num_keys, num_ckeys, num_keys + num_ckeys); 952 } 953 954 return desc_res.m_result; 955 } 956 957 static DBErrors LoadAddressBookRecords(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) 958 { 959 AssertLockHeld(pwallet->cs_wallet); 960 DBErrors result = DBErrors::LOAD_OK; 961 962 // Load name record 963 LoadResult name_res = LoadRecords(pwallet, batch, DBKeys::NAME, 964 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { 965 std::string strAddress; 966 key >> strAddress; 967 std::string label; 968 value >> label; 969 pwallet->m_address_book[DecodeDestination(strAddress)].SetLabel(label); 970 return DBErrors::LOAD_OK; 971 }); 972 result = std::max(result, name_res.m_result); 973 974 // Load purpose record 975 LoadResult purpose_res = LoadRecords(pwallet, batch, DBKeys::PURPOSE, 976 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { 977 std::string strAddress; 978 key >> strAddress; 979 std::string purpose_str; 980 value >> purpose_str; 981 std::optional<AddressPurpose> purpose{PurposeFromString(purpose_str)}; 982 if (!purpose) { 983 pwallet->WalletLogPrintf("Warning: nonstandard purpose string '%s' for address '%s'\n", purpose_str, strAddress); 984 } 985 pwallet->m_address_book[DecodeDestination(strAddress)].purpose = purpose; 986 return DBErrors::LOAD_OK; 987 }); 988 result = std::max(result, purpose_res.m_result); 989 990 // Load destination data record 991 LoadResult dest_res = LoadRecords(pwallet, batch, DBKeys::DESTDATA, 992 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { 993 std::string strAddress, strKey, strValue; 994 key >> strAddress; 995 key >> strKey; 996 value >> strValue; 997 const CTxDestination& dest{DecodeDestination(strAddress)}; 998 if (strKey.compare("used") == 0) { 999 // Load "used" key indicating if an IsMine address has 1000 // previously been spent from with avoid_reuse option enabled. 1001 // The strValue is not used for anything currently, but could 1002 // hold more information in the future. Current values are just 1003 // "1" or "p" for present (which was written prior to 1004 // f5ba424cd44619d9b9be88b8593d69a7ba96db26). 1005 pwallet->LoadAddressPreviouslySpent(dest); 1006 } else if (strKey.compare(0, 2, "rr") == 0) { 1007 // Load "rr##" keys where ## is a decimal number, and strValue 1008 // is a serialized RecentRequestEntry object. 1009 pwallet->LoadAddressReceiveRequest(dest, strKey.substr(2), strValue); 1010 } 1011 return DBErrors::LOAD_OK; 1012 }); 1013 result = std::max(result, dest_res.m_result); 1014 1015 return result; 1016 } 1017 1018 static DBErrors LoadTxRecords(CWallet* pwallet, DatabaseBatch& batch, std::vector<uint256>& upgraded_txs, bool& any_unordered) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) 1019 { 1020 AssertLockHeld(pwallet->cs_wallet); 1021 DBErrors result = DBErrors::LOAD_OK; 1022 1023 // Load tx record 1024 any_unordered = false; 1025 LoadResult tx_res = LoadRecords(pwallet, batch, DBKeys::TX, 1026 [&any_unordered, &upgraded_txs] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { 1027 DBErrors result = DBErrors::LOAD_OK; 1028 uint256 hash; 1029 key >> hash; 1030 // LoadToWallet call below creates a new CWalletTx that fill_wtx 1031 // callback fills with transaction metadata. 1032 auto fill_wtx = [&](CWalletTx& wtx, bool new_tx) { 1033 if(!new_tx) { 1034 // There's some corruption here since the tx we just tried to load was already in the wallet. 1035 err = "Error: Corrupt transaction found. This can be fixed by removing transactions from wallet and rescanning."; 1036 result = DBErrors::CORRUPT; 1037 return false; 1038 } 1039 value >> wtx; 1040 if (wtx.GetHash() != hash) 1041 return false; 1042 1043 // Undo serialize changes in 31600 1044 if (31404 <= wtx.fTimeReceivedIsTxTime && wtx.fTimeReceivedIsTxTime <= 31703) 1045 { 1046 if (!value.empty()) 1047 { 1048 uint8_t fTmp; 1049 uint8_t fUnused; 1050 std::string unused_string; 1051 value >> fTmp >> fUnused >> unused_string; 1052 pwallet->WalletLogPrintf("LoadWallet() upgrading tx ver=%d %d %s\n", 1053 wtx.fTimeReceivedIsTxTime, fTmp, hash.ToString()); 1054 wtx.fTimeReceivedIsTxTime = fTmp; 1055 } 1056 else 1057 { 1058 pwallet->WalletLogPrintf("LoadWallet() repairing tx ver=%d %s\n", wtx.fTimeReceivedIsTxTime, hash.ToString()); 1059 wtx.fTimeReceivedIsTxTime = 0; 1060 } 1061 upgraded_txs.push_back(hash); 1062 } 1063 1064 if (wtx.nOrderPos == -1) 1065 any_unordered = true; 1066 1067 return true; 1068 }; 1069 if (!pwallet->LoadToWallet(hash, fill_wtx)) { 1070 // Use std::max as fill_wtx may have already set result to CORRUPT 1071 result = std::max(result, DBErrors::NEED_RESCAN); 1072 } 1073 return result; 1074 }); 1075 result = std::max(result, tx_res.m_result); 1076 1077 // Load locked utxo record 1078 LoadResult locked_utxo_res = LoadRecords(pwallet, batch, DBKeys::LOCKED_UTXO, 1079 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { 1080 Txid hash; 1081 uint32_t n; 1082 key >> hash; 1083 key >> n; 1084 pwallet->LockCoin(COutPoint(hash, n)); 1085 return DBErrors::LOAD_OK; 1086 }); 1087 result = std::max(result, locked_utxo_res.m_result); 1088 1089 // Load orderposnext record 1090 // Note: There should only be one ORDERPOSNEXT record with nothing trailing the type 1091 LoadResult order_pos_res = LoadRecords(pwallet, batch, DBKeys::ORDERPOSNEXT, 1092 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) { 1093 try { 1094 value >> pwallet->nOrderPosNext; 1095 } catch (const std::exception& e) { 1096 err = e.what(); 1097 return DBErrors::NONCRITICAL_ERROR; 1098 } 1099 return DBErrors::LOAD_OK; 1100 }); 1101 result = std::max(result, order_pos_res.m_result); 1102 1103 return result; 1104 } 1105 1106 static DBErrors LoadActiveSPKMs(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) 1107 { 1108 AssertLockHeld(pwallet->cs_wallet); 1109 DBErrors result = DBErrors::LOAD_OK; 1110 1111 // Load spk records 1112 std::set<std::pair<OutputType, bool>> seen_spks; 1113 for (const auto& spk_key : {DBKeys::ACTIVEEXTERNALSPK, DBKeys::ACTIVEINTERNALSPK}) { 1114 LoadResult spkm_res = LoadRecords(pwallet, batch, spk_key, 1115 [&seen_spks, &spk_key] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& strErr) { 1116 uint8_t output_type; 1117 key >> output_type; 1118 uint256 id; 1119 value >> id; 1120 1121 bool internal = spk_key == DBKeys::ACTIVEINTERNALSPK; 1122 auto [it, insert] = seen_spks.emplace(static_cast<OutputType>(output_type), internal); 1123 if (!insert) { 1124 strErr = "Multiple ScriptpubKeyMans specified for a single type"; 1125 return DBErrors::CORRUPT; 1126 } 1127 pwallet->LoadActiveScriptPubKeyMan(id, static_cast<OutputType>(output_type), /*internal=*/internal); 1128 return DBErrors::LOAD_OK; 1129 }); 1130 result = std::max(result, spkm_res.m_result); 1131 } 1132 return result; 1133 } 1134 1135 static DBErrors LoadDecryptionKeys(CWallet* pwallet, DatabaseBatch& batch) EXCLUSIVE_LOCKS_REQUIRED(pwallet->cs_wallet) 1136 { 1137 AssertLockHeld(pwallet->cs_wallet); 1138 1139 // Load decryption key (mkey) records 1140 LoadResult mkey_res = LoadRecords(pwallet, batch, DBKeys::MASTER_KEY, 1141 [] (CWallet* pwallet, DataStream& key, DataStream& value, std::string& err) { 1142 if (!LoadEncryptionKey(pwallet, key, value, err)) { 1143 return DBErrors::CORRUPT; 1144 } 1145 return DBErrors::LOAD_OK; 1146 }); 1147 return mkey_res.m_result; 1148 } 1149 1150 DBErrors WalletBatch::LoadWallet(CWallet* pwallet) 1151 { 1152 DBErrors result = DBErrors::LOAD_OK; 1153 bool any_unordered = false; 1154 std::vector<uint256> upgraded_txs; 1155 1156 LOCK(pwallet->cs_wallet); 1157 1158 // Last client version to open this wallet 1159 int last_client = CLIENT_VERSION; 1160 bool has_last_client = m_batch->Read(DBKeys::VERSION, last_client); 1161 pwallet->WalletLogPrintf("Wallet file version = %d, last client version = %d\n", pwallet->GetVersion(), last_client); 1162 1163 try { 1164 if ((result = LoadMinVersion(pwallet, *m_batch)) != DBErrors::LOAD_OK) return result; 1165 1166 // Load wallet flags, so they are known when processing other records. 1167 // The FLAGS key is absent during wallet creation. 1168 if ((result = LoadWalletFlags(pwallet, *m_batch)) != DBErrors::LOAD_OK) return result; 1169 1170 #ifndef ENABLE_EXTERNAL_SIGNER 1171 if (pwallet->IsWalletFlagSet(WALLET_FLAG_EXTERNAL_SIGNER)) { 1172 pwallet->WalletLogPrintf("Error: External signer wallet being loaded without external signer support compiled\n"); 1173 return DBErrors::EXTERNAL_SIGNER_SUPPORT_REQUIRED; 1174 } 1175 #endif 1176 1177 // Load legacy wallet keys 1178 result = std::max(LoadLegacyWalletRecords(pwallet, *m_batch, last_client), result); 1179 1180 // Load descriptors 1181 result = std::max(LoadDescriptorWalletRecords(pwallet, *m_batch, last_client), result); 1182 // Early return if there are unknown descriptors. Later loading of ACTIVEINTERNALSPK and ACTIVEEXTERNALEXPK 1183 // may reference the unknown descriptor's ID which can result in a misleading corruption error 1184 // when in reality the wallet is simply too new. 1185 if (result == DBErrors::UNKNOWN_DESCRIPTOR) return result; 1186 1187 // Load address book 1188 result = std::max(LoadAddressBookRecords(pwallet, *m_batch), result); 1189 1190 // Load tx records 1191 result = std::max(LoadTxRecords(pwallet, *m_batch, upgraded_txs, any_unordered), result); 1192 1193 // Load SPKMs 1194 result = std::max(LoadActiveSPKMs(pwallet, *m_batch), result); 1195 1196 // Load decryption keys 1197 result = std::max(LoadDecryptionKeys(pwallet, *m_batch), result); 1198 } catch (...) { 1199 // Exceptions that can be ignored or treated as non-critical are handled by the individual loading functions. 1200 // Any uncaught exceptions will be caught here and treated as critical. 1201 result = DBErrors::CORRUPT; 1202 } 1203 1204 // Any wallet corruption at all: skip any rewriting or 1205 // upgrading, we don't want to make it worse. 1206 if (result != DBErrors::LOAD_OK) 1207 return result; 1208 1209 for (const uint256& hash : upgraded_txs) 1210 WriteTx(pwallet->mapWallet.at(hash)); 1211 1212 if (!has_last_client || last_client != CLIENT_VERSION) // Update 1213 m_batch->Write(DBKeys::VERSION, CLIENT_VERSION); 1214 1215 if (any_unordered) 1216 result = pwallet->ReorderTransactions(); 1217 1218 // Upgrade all of the wallet keymetadata to have the hd master key id 1219 // This operation is not atomic, but if it fails, updated entries are still backwards compatible with older software 1220 try { 1221 pwallet->UpgradeKeyMetadata(); 1222 } catch (...) { 1223 result = DBErrors::CORRUPT; 1224 } 1225 1226 // Upgrade all of the descriptor caches to cache the last hardened xpub 1227 // This operation is not atomic, but if it fails, only new entries are added so it is backwards compatible 1228 try { 1229 pwallet->UpgradeDescriptorCache(); 1230 } catch (...) { 1231 result = DBErrors::CORRUPT; 1232 } 1233 1234 return result; 1235 } 1236 1237 static bool RunWithinTxn(WalletBatch& batch, std::string_view process_desc, const std::function<bool(WalletBatch&)>& func) 1238 { 1239 if (!batch.TxnBegin()) { 1240 LogPrint(BCLog::WALLETDB, "Error: cannot create db txn for %s\n", process_desc); 1241 return false; 1242 } 1243 1244 // Run procedure 1245 if (!func(batch)) { 1246 LogPrint(BCLog::WALLETDB, "Error: %s failed\n", process_desc); 1247 batch.TxnAbort(); 1248 return false; 1249 } 1250 1251 if (!batch.TxnCommit()) { 1252 LogPrint(BCLog::WALLETDB, "Error: cannot commit db txn for %s\n", process_desc); 1253 return false; 1254 } 1255 1256 // All good 1257 return true; 1258 } 1259 1260 bool RunWithinTxn(WalletDatabase& database, std::string_view process_desc, const std::function<bool(WalletBatch&)>& func) 1261 { 1262 WalletBatch batch(database); 1263 return RunWithinTxn(batch, process_desc, func); 1264 } 1265 1266 void MaybeCompactWalletDB(WalletContext& context) 1267 { 1268 static std::atomic<bool> fOneThread(false); 1269 if (fOneThread.exchange(true)) { 1270 return; 1271 } 1272 1273 for (const std::shared_ptr<CWallet>& pwallet : GetWallets(context)) { 1274 WalletDatabase& dbh = pwallet->GetDatabase(); 1275 1276 unsigned int nUpdateCounter = dbh.nUpdateCounter; 1277 1278 if (dbh.nLastSeen != nUpdateCounter) { 1279 dbh.nLastSeen = nUpdateCounter; 1280 dbh.nLastWalletUpdate = GetTime(); 1281 } 1282 1283 if (dbh.nLastFlushed != nUpdateCounter && GetTime() - dbh.nLastWalletUpdate >= 2) { 1284 if (dbh.PeriodicFlush()) { 1285 dbh.nLastFlushed = nUpdateCounter; 1286 } 1287 } 1288 } 1289 1290 fOneThread = false; 1291 } 1292 1293 bool WalletBatch::WriteAddressPreviouslySpent(const CTxDestination& dest, bool previously_spent) 1294 { 1295 auto key{std::make_pair(DBKeys::DESTDATA, std::make_pair(EncodeDestination(dest), std::string("used")))}; 1296 return previously_spent ? WriteIC(key, std::string("1")) : EraseIC(key); 1297 } 1298 1299 bool WalletBatch::WriteAddressReceiveRequest(const CTxDestination& dest, const std::string& id, const std::string& receive_request) 1300 { 1301 return WriteIC(std::make_pair(DBKeys::DESTDATA, std::make_pair(EncodeDestination(dest), "rr" + id)), receive_request); 1302 } 1303 1304 bool WalletBatch::EraseAddressReceiveRequest(const CTxDestination& dest, const std::string& id) 1305 { 1306 return EraseIC(std::make_pair(DBKeys::DESTDATA, std::make_pair(EncodeDestination(dest), "rr" + id))); 1307 } 1308 1309 bool WalletBatch::EraseAddressData(const CTxDestination& dest) 1310 { 1311 DataStream prefix; 1312 prefix << DBKeys::DESTDATA << EncodeDestination(dest); 1313 return m_batch->ErasePrefix(prefix); 1314 } 1315 1316 bool WalletBatch::WriteHDChain(const CHDChain& chain) 1317 { 1318 return WriteIC(DBKeys::HDCHAIN, chain); 1319 } 1320 1321 bool WalletBatch::WriteWalletFlags(const uint64_t flags) 1322 { 1323 return WriteIC(DBKeys::FLAGS, flags); 1324 } 1325 1326 bool WalletBatch::EraseRecords(const std::unordered_set<std::string>& types) 1327 { 1328 return RunWithinTxn(*this, "erase records", [&types](WalletBatch& self) { 1329 return std::all_of(types.begin(), types.end(), [&self](const std::string& type) { 1330 return self.m_batch->ErasePrefix(DataStream() << type); 1331 }); 1332 }); 1333 } 1334 1335 bool WalletBatch::TxnBegin() 1336 { 1337 return m_batch->TxnBegin(); 1338 } 1339 1340 bool WalletBatch::TxnCommit() 1341 { 1342 return m_batch->TxnCommit(); 1343 } 1344 1345 bool WalletBatch::TxnAbort() 1346 { 1347 return m_batch->TxnAbort(); 1348 } 1349 1350 std::unique_ptr<WalletDatabase> MakeDatabase(const fs::path& path, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error) 1351 { 1352 bool exists; 1353 try { 1354 exists = fs::symlink_status(path).type() != fs::file_type::not_found; 1355 } catch (const fs::filesystem_error& e) { 1356 error = Untranslated(strprintf("Failed to access database path '%s': %s", fs::PathToString(path), fsbridge::get_filesystem_error_message(e))); 1357 status = DatabaseStatus::FAILED_BAD_PATH; 1358 return nullptr; 1359 } 1360 1361 std::optional<DatabaseFormat> format; 1362 if (exists) { 1363 if (IsBDBFile(BDBDataFile(path))) { 1364 format = DatabaseFormat::BERKELEY; 1365 } 1366 if (IsSQLiteFile(SQLiteDataFile(path))) { 1367 if (format) { 1368 error = Untranslated(strprintf("Failed to load database path '%s'. Data is in ambiguous format.", fs::PathToString(path))); 1369 status = DatabaseStatus::FAILED_BAD_FORMAT; 1370 return nullptr; 1371 } 1372 format = DatabaseFormat::SQLITE; 1373 } 1374 } else if (options.require_existing) { 1375 error = Untranslated(strprintf("Failed to load database path '%s'. Path does not exist.", fs::PathToString(path))); 1376 status = DatabaseStatus::FAILED_NOT_FOUND; 1377 return nullptr; 1378 } 1379 1380 if (!format && options.require_existing) { 1381 error = Untranslated(strprintf("Failed to load database path '%s'. Data is not in recognized format.", fs::PathToString(path))); 1382 status = DatabaseStatus::FAILED_BAD_FORMAT; 1383 return nullptr; 1384 } 1385 1386 if (format && options.require_create) { 1387 error = Untranslated(strprintf("Failed to create database path '%s'. Database already exists.", fs::PathToString(path))); 1388 status = DatabaseStatus::FAILED_ALREADY_EXISTS; 1389 return nullptr; 1390 } 1391 1392 // A db already exists so format is set, but options also specifies the format, so make sure they agree 1393 if (format && options.require_format && format != options.require_format) { 1394 error = Untranslated(strprintf("Failed to load database path '%s'. Data is not in required format.", fs::PathToString(path))); 1395 status = DatabaseStatus::FAILED_BAD_FORMAT; 1396 return nullptr; 1397 } 1398 1399 // Format is not set when a db doesn't already exist, so use the format specified by the options if it is set. 1400 if (!format && options.require_format) format = options.require_format; 1401 1402 // If the format is not specified or detected, choose the default format based on what is available. We prefer BDB over SQLite for now. 1403 if (!format) { 1404 #ifdef USE_SQLITE 1405 format = DatabaseFormat::SQLITE; 1406 #endif 1407 #ifdef USE_BDB 1408 format = DatabaseFormat::BERKELEY; 1409 #endif 1410 } 1411 1412 if (format == DatabaseFormat::SQLITE) { 1413 #ifdef USE_SQLITE 1414 if constexpr (true) { 1415 return MakeSQLiteDatabase(path, options, status, error); 1416 } else 1417 #endif 1418 { 1419 error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support SQLite database format.", fs::PathToString(path))); 1420 status = DatabaseStatus::FAILED_BAD_FORMAT; 1421 return nullptr; 1422 } 1423 } 1424 1425 #ifdef USE_BDB 1426 if constexpr (true) { 1427 return MakeBerkeleyDatabase(path, options, status, error); 1428 } else 1429 #endif 1430 { 1431 error = Untranslated(strprintf("Failed to open database path '%s'. Build does not support Berkeley DB database format.", fs::PathToString(path))); 1432 status = DatabaseStatus::FAILED_BAD_FORMAT; 1433 return nullptr; 1434 } 1435 } 1436 } // namespace wallet