diff options
-rw-r--r-- | src/wallet/rpc/backup.cpp | 97 | ||||
-rw-r--r-- | src/wallet/rpcwallet.cpp | 101 | ||||
-rw-r--r-- | src/wallet/rpcwallet.h | 8 |
3 files changed, 108 insertions, 98 deletions
diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp index e7eaa7076d..79a23f2a3b 100644 --- a/src/wallet/rpc/backup.cpp +++ b/src/wallet/rpc/backup.cpp @@ -17,6 +17,7 @@ #include <util/system.h> #include <util/time.h> #include <util/translation.h> +#include <wallet/rpcwallet.h> #include <wallet/rpc/util.h> #include <wallet/wallet.h> @@ -1831,3 +1832,99 @@ RPCHelpMan listdescriptors() }, }; } + +RPCHelpMan backupwallet() +{ + return RPCHelpMan{"backupwallet", + "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n", + { + {"destination", RPCArg::Type::STR, RPCArg::Optional::NO, "The destination directory or file"}, + }, + RPCResult{RPCResult::Type::NONE, "", ""}, + RPCExamples{ + HelpExampleCli("backupwallet", "\"backup.dat\"") + + HelpExampleRpc("backupwallet", "\"backup.dat\"") + }, + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue +{ + const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request); + if (!pwallet) return NullUniValue; + + // Make sure the results are valid at least up to the most recent block + // the user could have gotten from another RPC command prior to now + pwallet->BlockUntilSyncedToCurrentChain(); + + LOCK(pwallet->cs_wallet); + + std::string strDest = request.params[0].get_str(); + if (!pwallet->BackupWallet(strDest)) { + throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!"); + } + + return NullUniValue; +}, + }; +} + + +RPCHelpMan restorewallet() +{ + return RPCHelpMan{ + "restorewallet", + "\nRestore and loads a wallet from backup.\n", + { + {"wallet_name", RPCArg::Type::STR, RPCArg::Optional::NO, "The name that will be applied to the restored wallet"}, + {"backup_file", RPCArg::Type::STR, RPCArg::Optional::NO, "The backup file that will be used to restore the wallet."}, + {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED_NAMED_ARG, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."}, + }, + RPCResult{ + RPCResult::Type::OBJ, "", "", + { + {RPCResult::Type::STR, "name", "The wallet name if restored successfully."}, + {RPCResult::Type::STR, "warning", "Warning message if wallet was not loaded cleanly."}, + } + }, + RPCExamples{ + HelpExampleCli("restorewallet", "\"testwallet\" \"home\\backups\\backup-file.bak\"") + + HelpExampleRpc("restorewallet", "\"testwallet\" \"home\\backups\\backup-file.bak\"") + + HelpExampleCliNamed("restorewallet", {{"wallet_name", "testwallet"}, {"backup_file", "home\\backups\\backup-file.bak\""}, {"load_on_startup", true}}) + + HelpExampleRpcNamed("restorewallet", {{"wallet_name", "testwallet"}, {"backup_file", "home\\backups\\backup-file.bak\""}, {"load_on_startup", true}}) + }, + [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue +{ + + WalletContext& context = EnsureWalletContext(request.context); + + auto backup_file = fs::u8path(request.params[1].get_str()); + + if (!fs::exists(backup_file)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Backup file does not exist"); + } + + std::string wallet_name = request.params[0].get_str(); + + const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::u8path(wallet_name)); + + if (fs::exists(wallet_path)) { + throw JSONRPCError(RPC_INVALID_PARAMETER, "Wallet name already exists."); + } + + if (!TryCreateDirectories(wallet_path)) { + throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Failed to create database path '%s'. Database already exists.", wallet_path.u8string())); + } + + auto wallet_file = wallet_path / "wallet.dat"; + + fs::copy_file(backup_file, wallet_file, fs::copy_option::fail_if_exists); + + auto [wallet, warnings] = LoadWalletHelper(context, request.params[2], wallet_name); + + UniValue obj(UniValue::VOBJ); + obj.pushKV("name", wallet->GetName()); + obj.pushKV("warning", Join(warnings, Untranslated("\n")).original); + + return obj; + +}, + }; +} diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index 77b3cfe4dc..ac7a62c7fa 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -1656,41 +1656,6 @@ static RPCHelpMan abandontransaction() }; } - -static RPCHelpMan backupwallet() -{ - return RPCHelpMan{"backupwallet", - "\nSafely copies current wallet file to destination, which can be a directory or a path with filename.\n", - { - {"destination", RPCArg::Type::STR, RPCArg::Optional::NO, "The destination directory or file"}, - }, - RPCResult{RPCResult::Type::NONE, "", ""}, - RPCExamples{ - HelpExampleCli("backupwallet", "\"backup.dat\"") - + HelpExampleRpc("backupwallet", "\"backup.dat\"") - }, - [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue -{ - const std::shared_ptr<const CWallet> pwallet = GetWalletForJSONRPCRequest(request); - if (!pwallet) return NullUniValue; - - // Make sure the results are valid at least up to the most recent block - // the user could have gotten from another RPC command prior to now - pwallet->BlockUntilSyncedToCurrentChain(); - - LOCK(pwallet->cs_wallet); - - std::string strDest = request.params[0].get_str(); - if (!pwallet->BackupWallet(strDest)) { - throw JSONRPCError(RPC_WALLET_ERROR, "Error: Wallet backup failed!"); - } - - return NullUniValue; -}, - }; -} - - static RPCHelpMan keypoolrefill() { return RPCHelpMan{"keypoolrefill", @@ -2467,7 +2432,7 @@ static RPCHelpMan listwallets() }; } -static std::tuple<std::shared_ptr<CWallet>, std::vector<bilingual_str>> LoadWalletHelper(WalletContext& context, UniValue load_on_start_param, const std::string wallet_name) +std::tuple<std::shared_ptr<CWallet>, std::vector<bilingual_str>> LoadWalletHelper(WalletContext& context, UniValue load_on_start_param, const std::string wallet_name) { DatabaseOptions options; DatabaseStatus status; @@ -2697,68 +2662,6 @@ static RPCHelpMan createwallet() }; } -static RPCHelpMan restorewallet() -{ - return RPCHelpMan{ - "restorewallet", - "\nRestore and loads a wallet from backup.\n", - { - {"wallet_name", RPCArg::Type::STR, RPCArg::Optional::NO, "The name that will be applied to the restored wallet"}, - {"backup_file", RPCArg::Type::STR, RPCArg::Optional::NO, "The backup file that will be used to restore the wallet."}, - {"load_on_startup", RPCArg::Type::BOOL, RPCArg::Optional::OMITTED_NAMED_ARG, "Save wallet name to persistent settings and load on startup. True to add wallet to startup list, false to remove, null to leave unchanged."}, - }, - RPCResult{ - RPCResult::Type::OBJ, "", "", - { - {RPCResult::Type::STR, "name", "The wallet name if restored successfully."}, - {RPCResult::Type::STR, "warning", "Warning message if wallet was not loaded cleanly."}, - } - }, - RPCExamples{ - HelpExampleCli("restorewallet", "\"testwallet\" \"home\\backups\\backup-file.bak\"") - + HelpExampleRpc("restorewallet", "\"testwallet\" \"home\\backups\\backup-file.bak\"") - + HelpExampleCliNamed("restorewallet", {{"wallet_name", "testwallet"}, {"backup_file", "home\\backups\\backup-file.bak\""}, {"load_on_startup", true}}) - + HelpExampleRpcNamed("restorewallet", {{"wallet_name", "testwallet"}, {"backup_file", "home\\backups\\backup-file.bak\""}, {"load_on_startup", true}}) - }, - [&](const RPCHelpMan& self, const JSONRPCRequest& request) -> UniValue -{ - - WalletContext& context = EnsureWalletContext(request.context); - - auto backup_file = fs::u8path(request.params[1].get_str()); - - if (!fs::exists(backup_file)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Backup file does not exist"); - } - - std::string wallet_name = request.params[0].get_str(); - - const fs::path wallet_path = fsbridge::AbsPathJoin(GetWalletDir(), fs::u8path(wallet_name)); - - if (fs::exists(wallet_path)) { - throw JSONRPCError(RPC_INVALID_PARAMETER, "Wallet name already exists."); - } - - if (!TryCreateDirectories(wallet_path)) { - throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Failed to create database path '%s'. Database already exists.", wallet_path.u8string())); - } - - auto wallet_file = wallet_path / "wallet.dat"; - - fs::copy_file(backup_file, wallet_file, fs::copy_option::fail_if_exists); - - auto [wallet, warnings] = LoadWalletHelper(context, request.params[2], wallet_name); - - UniValue obj(UniValue::VOBJ); - obj.pushKV("name", wallet->GetName()); - obj.pushKV("warning", Join(warnings, Untranslated("\n")).original); - - return obj; - -}, - }; -} - static RPCHelpMan unloadwallet() { return RPCHelpMan{"unloadwallet", @@ -4699,6 +4602,8 @@ RPCHelpMan importmulti(); RPCHelpMan importdescriptors(); RPCHelpMan listdescriptors(); RPCHelpMan signmessage(); +RPCHelpMan backupwallet(); +RPCHelpMan restorewallet(); Span<const CRPCCommand> GetWalletRPCCommands() { diff --git a/src/wallet/rpcwallet.h b/src/wallet/rpcwallet.h index 2c3d413cb0..1c222df7b6 100644 --- a/src/wallet/rpcwallet.h +++ b/src/wallet/rpcwallet.h @@ -7,10 +7,18 @@ #include <span.h> +#include <memory> +#include <string> +#include <vector> + class CRPCCommand; +class CWallet; +struct WalletContext; Span<const CRPCCommand> GetWalletRPCCommands(); +std::tuple<std::shared_ptr<CWallet>, std::vector<bilingual_str>> LoadWalletHelper(WalletContext& context, UniValue load_on_start_param, const std::string wallet_name); + RPCHelpMan getaddressinfo(); RPCHelpMan signrawtransactionwithwallet(); #endif // BITCOIN_WALLET_RPCWALLET_H |