mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-01-25 02:33:24 -03:00
refactor: Move restorewallet() RPC logic to the wallet section
It also simplifies restorewallet() and loadwallet() RPC error handling.
This commit is contained in:
parent
4807f73f48
commit
abbb7eccef
8 changed files with 34 additions and 33 deletions
|
@ -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,
|
||||
|
|
|
@ -220,6 +220,7 @@ enum class DatabaseStatus {
|
|||
FAILED_LOAD,
|
||||
FAILED_VERIFY,
|
||||
FAILED_ENCRYPT,
|
||||
FAILED_INVALID_BACKUP_FILE,
|
||||
};
|
||||
|
||||
/** Recursively list database paths in directory. */
|
||||
|
|
|
@ -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));
|
||||
std::optional<bool> load_on_start = request.params[2].isNull() ? std::nullopt : std::optional<bool>(request.params[2].get_bool());
|
||||
|
||||
if (fs::exists(wallet_path)) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "Wallet name already exists.");
|
||||
}
|
||||
DatabaseStatus status;
|
||||
bilingual_str error;
|
||||
std::vector<bilingual_str> warnings;
|
||||
|
||||
if (!TryCreateDirectories(wallet_path)) {
|
||||
throw JSONRPCError(RPC_WALLET_ERROR, strprintf("Failed to create database path '%s'. Database already exists.", wallet_path.u8string()));
|
||||
}
|
||||
const std::shared_ptr<CWallet> wallet = RestoreWallet(context, fs::PathToString(backup_file), wallet_name, load_on_start, status, error, warnings);
|
||||
|
||||
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);
|
||||
HandleWalletError(wallet, status, error);
|
||||
|
||||
UniValue obj(UniValue::VOBJ);
|
||||
obj.pushKV("name", wallet->GetName());
|
||||
|
|
|
@ -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 };
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue