| 498 | |
| 499 | |
| 500 | RPCHelpMan importwallet() |
| 501 | { |
| 502 | return RPCHelpMan{"importwallet", |
| 503 | "\nImports keys from a wallet dump file (see dumpwallet). Requires a new wallet backup to include imported keys.\n" |
| 504 | "Note: Use \"getwalletinfo\" to query the scanning progress.\n", |
| 505 | { |
| 506 | {"filename", RPCArg::Type::STR, RPCArg::Optional::NO, "The wallet file"}, |
| 507 | }, |
| 508 | RPCResult{RPCResult::Type::NONE, "", ""}, |
| 509 | RPCExamples{ |
| 510 | "\nDump the wallet\n" |
| 511 | + HelpExampleCli("dumpwallet", "\"test\"") + |
| 512 | "\nImport the wallet\n" |
| 513 | + HelpExampleCli("importwallet", "\"test\"") + |
| 514 | "\nImport using the json rpc call\n" |
| 515 | + HelpExampleRpc("importwallet", "\"test\"") |
| 516 | }, |
| 517 | [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue |
| 518 | { |
| 519 | std::shared_ptr<CWallet> const pwallet = GetWalletForJSONRPCRequest(request); |
| 520 | if (!pwallet) return NullUniValue; |
| 521 | |
| 522 | EnsureLegacyScriptPubKeyMan(*pwallet, true); |
| 523 | |
| 524 | if (pwallet->chain().havePruned()) { |
| 525 | // Exit early and print an error. |
| 526 | // If a block is pruned after this check, we will import the key(s), |
| 527 | // but fail the rescan with a generic error. |
| 528 | throw JSONRPCError(RPC_WALLET_ERROR, "Importing wallets is disabled when blocks are pruned"); |
| 529 | } |
| 530 | |
| 531 | WalletRescanReserver reserver(*pwallet); |
| 532 | if (!reserver.reserve()) { |
| 533 | throw JSONRPCError(RPC_WALLET_ERROR, "Wallet is currently rescanning. Abort existing rescan or wait."); |
| 534 | } |
| 535 | |
| 536 | int64_t nTimeBegin = 0; |
| 537 | bool fGood = true; |
| 538 | { |
| 539 | LOCK(pwallet->cs_wallet); |
| 540 | |
| 541 | EnsureWalletIsUnlocked(*pwallet); |
| 542 | |
| 543 | std::ifstream file; |
| 544 | file.open(fs::u8path(request.params[0].get_str()), std::ios::in | std::ios::ate); |
| 545 | if (!file.is_open()) { |
| 546 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); |
| 547 | } |
| 548 | CHECK_NONFATAL(pwallet->chain().findBlock(pwallet->GetLastBlockHash(), FoundBlock().time(nTimeBegin))); |
| 549 | |
| 550 | int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg()); |
| 551 | file.seekg(0, file.beg); |
| 552 | |
| 553 | // Use uiInterface.ShowProgress instead of pwallet.ShowProgress because pwallet.ShowProgress has a cancel button tied to AbortRescan which |
| 554 | // we don't want for this progress bar showing the import progress. uiInterface.ShowProgress does not have a cancel button. |
| 555 | pwallet->chain().showProgress(strprintf("%s " + _("Importing…").translated, pwallet->GetDisplayName()), 0, false); // show progress dialog in GUI |
| 556 | std::vector<std::tuple<CKey, int64_t, bool, std::string>> keys; |
| 557 | std::vector<std::pair<CScript, int64_t>> scripts; |