aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorw0xlt <94266259+w0xlt@users.noreply.github.com>2021-12-14 20:10:21 -0300
committerw0xlt <94266259+w0xlt@users.noreply.github.com>2021-12-15 18:41:40 -0300
commitabbb7eccef3fc1c36f34756458d2792f6661e29f (patch)
tree11d952213f1d1d8e63e472ed68d358a598be7fa4
parent4807f73f48f4ff1084fcf7aee94e5b14592bfda8 (diff)
downloadbitcoin-abbb7eccef3fc1c36f34756458d2792f6661e29f.tar.xz
refactor: Move restorewallet() RPC logic to the wallet section
It also simplifies restorewallet() and loadwallet() RPC error handling.
-rw-r--r--src/rpc/protocol.h1
-rw-r--r--src/wallet/db.h1
-rw-r--r--src/wallet/rpc/backup.cpp22
-rw-r--r--src/wallet/rpc/util.cpp20
-rw-r--r--src/wallet/rpc/util.h3
-rw-r--r--src/wallet/rpc/wallet.cpp10
-rw-r--r--src/wallet/wallet.cpp2
-rwxr-xr-xtest/functional/wallet_backup.py8
8 files changed, 34 insertions, 33 deletions
diff --git a/src/rpc/protocol.h b/src/rpc/protocol.h
index fc00a1efad..2fc9f55eba 100644
--- a/src/rpc/protocol.h
+++ b/src/rpc/protocol.h
@@ -80,6 +80,7 @@ enum RPCErrorCode
RPC_WALLET_NOT_FOUND = -18, //!< Invalid wallet specified
RPC_WALLET_NOT_SPECIFIED = -19, //!< No wallet specified (error when there are multiple wallets loaded)
RPC_WALLET_ALREADY_LOADED = -35, //!< This same wallet is already loaded
+ RPC_WALLET_ALREADY_EXISTS = -36, //!< There is already a wallet with the same name
//! Backwards compatible aliases
RPC_WALLET_INVALID_ACCOUNT_NAME = RPC_WALLET_INVALID_LABEL_NAME,
diff --git a/src/wallet/db.h b/src/wallet/db.h
index 7a0d3d2e07..3336099eb9 100644
--- a/src/wallet/db.h
+++ b/src/wallet/db.h
@@ -220,6 +220,7 @@ enum class DatabaseStatus {
FAILED_LOAD,
FAILED_VERIFY,
FAILED_ENCRYPT,
+ FAILED_INVALID_BACKUP_FILE,
};
/** Recursively list database paths in directory. */
diff --git a/src/wallet/rpc/backup.cpp b/src/wallet/rpc/backup.cpp
index 135c3a15f2..f9c8004394 100644
--- a/src/wallet/rpc/backup.cpp
+++ b/src/wallet/rpc/backup.cpp
@@ -1879,27 +1879,17 @@ RPCHelpMan restorewallet()
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()));
- }
+ std::optional<bool> load_on_start = request.params[2].isNull() ? std::nullopt : std::optional<bool>(request.params[2].get_bool());
- auto wallet_file = wallet_path / "wallet.dat";
+ DatabaseStatus status;
+ bilingual_str error;
+ std::vector<bilingual_str> warnings;
- fs::copy_file(backup_file, wallet_file, fs::copy_option::fail_if_exists);
+ const std::shared_ptr<CWallet> wallet = RestoreWallet(context, fs::PathToString(backup_file), wallet_name, load_on_start, status, error, warnings);
- auto [wallet, warnings] = LoadWalletHelper(context, request.params[2], wallet_name);
+ HandleWalletError(wallet, status, error);
UniValue obj(UniValue::VOBJ);
obj.pushKV("name", wallet->GetName());
diff --git a/src/wallet/rpc/util.cpp b/src/wallet/rpc/util.cpp
index e2126b7236..9a40a67ee5 100644
--- a/src/wallet/rpc/util.cpp
+++ b/src/wallet/rpc/util.cpp
@@ -122,16 +122,8 @@ std::string LabelFromValue(const UniValue& value)
return label;
}
-std::tuple<std::shared_ptr<CWallet>, std::vector<bilingual_str>> LoadWalletHelper(WalletContext& context, UniValue load_on_start_param, const std::string wallet_name)
+void HandleWalletError(const std::shared_ptr<CWallet> wallet, DatabaseStatus& status, bilingual_str& error)
{
- DatabaseOptions options;
- DatabaseStatus status;
- options.require_existing = true;
- bilingual_str error;
- std::vector<bilingual_str> warnings;
- std::optional<bool> load_on_start = load_on_start_param.isNull() ? std::nullopt : std::optional<bool>(load_on_start_param.get_bool());
- std::shared_ptr<CWallet> const wallet = LoadWallet(context, wallet_name, load_on_start, options, status, error, warnings);
-
if (!wallet) {
// Map bad format to not found, since bad format is returned when the
// wallet directory exists, but doesn't contain a data file.
@@ -144,11 +136,15 @@ std::tuple<std::shared_ptr<CWallet>, std::vector<bilingual_str>> LoadWalletHelpe
case DatabaseStatus::FAILED_ALREADY_LOADED:
code = RPC_WALLET_ALREADY_LOADED;
break;
+ case DatabaseStatus::FAILED_ALREADY_EXISTS:
+ code = RPC_WALLET_ALREADY_EXISTS;
+ break;
+ case DatabaseStatus::FAILED_INVALID_BACKUP_FILE:
+ code = RPC_INVALID_PARAMETER;
+ break;
default: // RPC_WALLET_ERROR is returned for all other cases.
break;
}
throw JSONRPCError(code, error.original);
}
-
- return { wallet, warnings };
-}
+} \ No newline at end of file
diff --git a/src/wallet/rpc/util.h b/src/wallet/rpc/util.h
index a1fa4d49b1..5b00d2abcb 100644
--- a/src/wallet/rpc/util.h
+++ b/src/wallet/rpc/util.h
@@ -12,6 +12,7 @@
struct bilingual_str;
class CWallet;
+enum class DatabaseStatus;
class JSONRPCRequest;
class LegacyScriptPubKeyMan;
class UniValue;
@@ -37,6 +38,6 @@ bool GetAvoidReuseFlag(const CWallet& wallet, const UniValue& param);
bool ParseIncludeWatchonly(const UniValue& include_watchonly, const CWallet& wallet);
std::string LabelFromValue(const UniValue& value);
-std::tuple<std::shared_ptr<CWallet>, std::vector<bilingual_str>> LoadWalletHelper(WalletContext& context, UniValue load_on_start_param, const std::string wallet_name);
+void HandleWalletError(const std::shared_ptr<CWallet> wallet, DatabaseStatus& status, bilingual_str& error);
#endif // BITCOIN_WALLET_RPC_UTIL_H
diff --git a/src/wallet/rpc/wallet.cpp b/src/wallet/rpc/wallet.cpp
index 99ffe5d964..31a5a01855 100644
--- a/src/wallet/rpc/wallet.cpp
+++ b/src/wallet/rpc/wallet.cpp
@@ -215,7 +215,15 @@ static RPCHelpMan loadwallet()
WalletContext& context = EnsureWalletContext(request.context);
const std::string name(request.params[0].get_str());
- auto [wallet, warnings] = LoadWalletHelper(context, request.params[1], name);
+ DatabaseOptions options;
+ DatabaseStatus status;
+ options.require_existing = true;
+ bilingual_str error;
+ std::vector<bilingual_str> warnings;
+ std::optional<bool> load_on_start = request.params[1].isNull() ? std::nullopt : std::optional<bool>(request.params[1].get_bool());
+ std::shared_ptr<CWallet> const wallet = LoadWallet(context, name, load_on_start, options, status, error, warnings);
+
+ HandleWalletError(wallet, status, error);
UniValue obj(UniValue::VOBJ);
obj.pushKV("name", wallet->GetName());
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 59ed8c2571..f2d1acb71f 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -364,7 +364,7 @@ std::shared_ptr<CWallet> RestoreWallet(WalletContext& context, const std::string
if (!fs::exists(fs::u8path(backup_file))) {
error = Untranslated("Backup file does not exist");
- status = DatabaseStatus::FAILED_BAD_PATH;
+ status = DatabaseStatus::FAILED_INVALID_BACKUP_FILE;
return nullptr;
}
diff --git a/test/functional/wallet_backup.py b/test/functional/wallet_backup.py
index 932df4fbff..4bcfc3aa71 100755
--- a/test/functional/wallet_backup.py
+++ b/test/functional/wallet_backup.py
@@ -115,12 +115,16 @@ class WalletBackupTest(BitcoinTestFramework):
nonexistent_wallet_file = os.path.join(self.nodes[0].datadir, 'nonexistent_wallet.bak')
wallet_name = "res0"
assert_raises_rpc_error(-8, "Backup file does not exist", node.restorewallet, wallet_name, nonexistent_wallet_file)
+ not_created_wallet_file = os.path.join(node.datadir, self.chain, 'wallets', wallet_name)
+ assert not os.path.exists(not_created_wallet_file)
def restore_wallet_existent_name(self):
node = self.nodes[3]
- wallet_file = os.path.join(self.nodes[0].datadir, 'wallet.bak')
+ backup_file = os.path.join(self.nodes[0].datadir, 'wallet.bak')
wallet_name = "res0"
- assert_raises_rpc_error(-8, "Wallet name already exists.", node.restorewallet, wallet_name, wallet_file)
+ wallet_file = os.path.join(node.datadir, self.chain, 'wallets', wallet_name)
+ error_message = "Failed to create database path '{}'. Database already exists.".format(wallet_file)
+ assert_raises_rpc_error(-36, error_message, node.restorewallet, wallet_name, backup_file)
def init_three(self):
self.init_wallet(node=0)