Re-creates wallet from the backup file by renaming and moving it into the wallet's directory. If 'load_after_restore=true', the wallet object will be fully initialized and appended to the context.
| 455 | // Re-creates wallet from the backup file by renaming and moving it into the wallet's directory. |
| 456 | // If 'load_after_restore=true', the wallet object will be fully initialized and appended to the context. |
| 457 | std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const fs::path& backup_file, const std::string& wallet_name, std::optional<bool> load_on_start, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings, bool load_after_restore, bool allow_unnamed) |
| 458 | { |
| 459 | // Error if the wallet name is empty and allow_unnamed == false |
| 460 | // allow_unnamed == true is only used by migration to migrate an unnamed wallet |
| 461 | if (!allow_unnamed && wallet_name.empty()) { |
| 462 | error = Untranslated("Wallet name cannot be empty"); |
| 463 | status = DatabaseStatus::FAILED_NEW_UNNAMED; |
| 464 | return nullptr; |
| 465 | } |
| 466 | |
| 467 | DatabaseOptions options; |
| 468 | ReadDatabaseArgs(*context.args, options); |
| 469 | options.require_existing = true; |
| 470 | |
| 471 | const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::u8path(wallet_name)); |
| 472 | auto wallet_file = wallet_path / "wallet.dat"; |
| 473 | std::shared_ptr<CWallet> wallet; |
| 474 | bool wallet_file_copied = false; |
| 475 | bool created_parent_dir = false; |
| 476 | |
| 477 | try { |
| 478 | if (!fs::exists(backup_file)) { |
| 479 | error = Untranslated("Backup file does not exist"); |
| 480 | status = DatabaseStatus::FAILED_INVALID_BACKUP_FILE; |
| 481 | return nullptr; |
| 482 | } |
| 483 | |
| 484 | // Wallet directories are allowed to exist, but must not contain a .dat file. |
| 485 | // Any existing wallet database is treated as a hard failure to prevent overwriting. |
| 486 | if (fs::exists(wallet_path)) { |
| 487 | // If this is a file, it is the db and we don't want to overwrite it. |
| 488 | if (!fs::is_directory(wallet_path)) { |
| 489 | error = Untranslated(strprintf("Failed to restore wallet. Database file exists '%s'.", fs::PathToString(wallet_path))); |
| 490 | status = DatabaseStatus::FAILED_ALREADY_EXISTS; |
| 491 | return nullptr; |
| 492 | } |
| 493 | |
| 494 | // Check we are not going to overwrite an existing db file |
| 495 | if (fs::exists(wallet_file)) { |
| 496 | error = Untranslated(strprintf("Failed to restore wallet. Database file exists in '%s'.", fs::PathToString(wallet_file))); |
| 497 | status = DatabaseStatus::FAILED_ALREADY_EXISTS; |
| 498 | return nullptr; |
| 499 | } |
| 500 | } else { |
| 501 | // The directory doesn't exist, create it |
| 502 | if (!TryCreateDirectories(wallet_path)) { |
| 503 | error = Untranslated(strprintf("Failed to restore database path '%s'.", fs::PathToString(wallet_path))); |
| 504 | status = DatabaseStatus::FAILED_ALREADY_EXISTS; |
| 505 | return nullptr; |
| 506 | } |
| 507 | created_parent_dir = true; |
| 508 | } |
| 509 | |
| 510 | fs::copy_file(backup_file, wallet_file, fs::copy_options::none); |
| 511 | wallet_file_copied = true; |
| 512 | |
| 513 | if (load_after_restore) { |
| 514 | wallet = LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings); |
no test coverage detected