| 677 | |
| 678 | |
| 679 | UniValue dumpwallet(const JSONRPCRequest& request) |
| 680 | { |
| 681 | std::shared_ptr<CWallet> const wallet = GetWalletForJSONRPCRequest(request); |
| 682 | CWallet* const pwallet = wallet.get(); |
| 683 | if (!EnsureWalletIsAvailable(pwallet, request.fHelp)) { |
| 684 | return NullUniValue; |
| 685 | } |
| 686 | |
| 687 | if (request.fHelp || request.params.size() != 1) |
| 688 | throw std::runtime_error( |
| 689 | "dumpwallet \"filename\"\n" |
| 690 | "\nDumps all wallet keys in a human-readable format to a server-side file. This does not allow overwriting existing files.\n" |
| 691 | "Imported scripts are included in the dumpfile, but corresponding BIP173 addresses, etc. may not be added automatically by importwallet.\n" |
| 692 | "Note that if your wallet contains keys which are not derived from your HD seed (e.g. imported keys), these are not covered by\n" |
| 693 | "only backing up the seed itself, and must be backed up too (e.g. ensure you back up the whole dumpfile).\n" |
| 694 | "\nArguments:\n" |
| 695 | "1. \"filename\" (string, required) The filename with path (either absolute or relative to bgoldd)\n" |
| 696 | "\nResult:\n" |
| 697 | "{ (json object)\n" |
| 698 | " \"filename\" : { (string) The filename with full absolute path\n" |
| 699 | "}\n" |
| 700 | "\nExamples:\n" |
| 701 | + HelpExampleCli("dumpwallet", "\"test\"") |
| 702 | + HelpExampleRpc("dumpwallet", "\"test\"") |
| 703 | ); |
| 704 | |
| 705 | LOCK2(cs_main, pwallet->cs_wallet); |
| 706 | |
| 707 | EnsureWalletIsUnlocked(pwallet); |
| 708 | |
| 709 | boost::filesystem::path filepath = request.params[0].get_str(); |
| 710 | filepath = boost::filesystem::absolute(filepath); |
| 711 | |
| 712 | /* Prevent arbitrary files from being overwritten. There have been reports |
| 713 | * that users have overwritten wallet files this way: |
| 714 | * https://github.com/bitcoin/bitcoin/issues/9934 |
| 715 | * It may also avoid other security issues. |
| 716 | */ |
| 717 | if (boost::filesystem::exists(filepath)) { |
| 718 | throw JSONRPCError(RPC_INVALID_PARAMETER, filepath.string() + " already exists. If you are sure this is what you want, move it out of the way first"); |
| 719 | } |
| 720 | |
| 721 | std::ofstream file; |
| 722 | file.open(filepath.string().c_str()); |
| 723 | if (!file.is_open()) |
| 724 | throw JSONRPCError(RPC_INVALID_PARAMETER, "Cannot open wallet dump file"); |
| 725 | |
| 726 | std::map<CTxDestination, int64_t> mapKeyBirth; |
| 727 | const std::map<CKeyID, int64_t>& mapKeyPool = pwallet->GetAllReserveKeys(); |
| 728 | pwallet->GetKeyBirthTimes(mapKeyBirth); |
| 729 | |
| 730 | std::set<CScriptID> scripts = pwallet->GetCScripts(); |
| 731 | // TODO: include scripts in GetKeyBirthTimes() output instead of separate |
| 732 | |
| 733 | // sort time/key pairs |
| 734 | std::vector<std::pair<int64_t, CKeyID> > vKeyBirth; |
| 735 | for (const auto& entry : mapKeyBirth) { |
| 736 | if (const CKeyID* keyID = boost::get<CKeyID>(&entry.first)) { // set and test |