Skip to content

Commit fae51a5

Browse files
author
MarcoFalke
committed
wallet: Avoid translating RPC errors when loading wallets
Common errors and warnings should be translated when displayed in the GUI, but not translated when displayed elsewhere. The wallet method CreateWalletFromFile does not know its caller, so this commit changes it to return a bilingual_str to the caller.
1 parent 608359b commit fae51a5

18 files changed

+149
-121
lines changed

src/dummywallet.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
class CWallet;
1010
enum class WalletCreationStatus;
11+
struct bilingual_str;
1112

1213
namespace interfaces {
1314
class Chain;
@@ -72,12 +73,12 @@ std::vector<std::shared_ptr<CWallet>> GetWallets()
7273
throw std::logic_error("Wallet function called in non-wallet build.");
7374
}
7475

75-
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector<std::string>& warnings)
76+
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings)
7677
{
7778
throw std::logic_error("Wallet function called in non-wallet build.");
7879
}
7980

80-
WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result)
81+
WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, std::shared_ptr<CWallet>& result)
8182
{
8283
throw std::logic_error("Wallet function called in non-wallet build.");
8384
}

src/interfaces/node.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ class CWallet;
4343
fs::path GetWalletDir();
4444
std::vector<fs::path> ListWalletDir();
4545
std::vector<std::shared_ptr<CWallet>> GetWallets();
46-
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::vector<std::string>& warnings);
47-
WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, std::shared_ptr<CWallet>& result);
46+
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings);
47+
WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, std::shared_ptr<CWallet>& result);
4848
std::unique_ptr<interfaces::Handler> HandleLoadWallet(interfaces::Node::LoadWalletFn load_wallet);
4949

5050
namespace interfaces {
@@ -259,11 +259,11 @@ class NodeImpl : public Node
259259
}
260260
return wallets;
261261
}
262-
std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::vector<std::string>& warnings) override
262+
std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
263263
{
264264
return MakeWallet(LoadWallet(*m_context.chain, name, error, warnings));
265265
}
266-
std::unique_ptr<Wallet> createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, WalletCreationStatus& status) override
266+
std::unique_ptr<Wallet> createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, WalletCreationStatus& status) override
267267
{
268268
std::shared_ptr<CWallet> wallet;
269269
status = CreateWallet(*m_context.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);

src/interfaces/node.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ class Coin;
2727
class RPCTimerInterface;
2828
class UniValue;
2929
class proxyType;
30+
enum class WalletCreationStatus;
3031
struct CNodeStateStats;
3132
struct NodeContext;
32-
enum class WalletCreationStatus;
33+
struct bilingual_str;
3334

3435
namespace interfaces {
3536
class Handler;
@@ -201,10 +202,10 @@ class Node
201202
//! Attempts to load a wallet from file or directory.
202203
//! The loaded wallet is also notified to handlers previously registered
203204
//! with handleLoadWallet.
204-
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::vector<std::string>& warnings) = 0;
205+
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
205206

206207
//! Create a wallet from file
207-
virtual std::unique_ptr<Wallet> createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, std::string& error, std::vector<std::string>& warnings, WalletCreationStatus& status) = 0;
208+
virtual std::unique_ptr<Wallet> createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, WalletCreationStatus& status) = 0;
208209

209210
//! Register handler for init messages.
210211
using InitMessageFn = std::function<void(const std::string& message)>;

src/qt/walletcontroller.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <interfaces/handler.h>
1515
#include <interfaces/node.h>
1616
#include <util/string.h>
17+
#include <util/translation.h>
1718
#include <wallet/wallet.h>
1819

1920
#include <algorithm>
@@ -244,10 +245,10 @@ void CreateWalletActivity::finish()
244245
{
245246
destroyProgressDialog();
246247

247-
if (!m_error_message.empty()) {
248-
QMessageBox::critical(m_parent_widget, tr("Create wallet failed"), QString::fromStdString(m_error_message));
248+
if (!m_error_message.original.empty()) {
249+
QMessageBox::critical(m_parent_widget, tr("Create wallet failed"), QString::fromStdString(m_error_message.translated));
249250
} else if (!m_warning_message.empty()) {
250-
QMessageBox::warning(m_parent_widget, tr("Create wallet warning"), QString::fromStdString(Join(m_warning_message, "\n")));
251+
QMessageBox::warning(m_parent_widget, tr("Create wallet warning"), QString::fromStdString(Join(m_warning_message, "\n", OpTranslated)));
251252
}
252253

253254
if (m_wallet_model) Q_EMIT created(m_wallet_model);
@@ -285,10 +286,10 @@ void OpenWalletActivity::finish()
285286
{
286287
destroyProgressDialog();
287288

288-
if (!m_error_message.empty()) {
289-
QMessageBox::critical(m_parent_widget, tr("Open wallet failed"), QString::fromStdString(m_error_message));
289+
if (!m_error_message.original.empty()) {
290+
QMessageBox::critical(m_parent_widget, tr("Open wallet failed"), QString::fromStdString(m_error_message.translated));
290291
} else if (!m_warning_message.empty()) {
291-
QMessageBox::warning(m_parent_widget, tr("Open wallet warning"), QString::fromStdString(Join(m_warning_message, "\n")));
292+
QMessageBox::warning(m_parent_widget, tr("Open wallet warning"), QString::fromStdString(Join(m_warning_message, "\n", OpTranslated)));
292293
}
293294

294295
if (m_wallet_model) Q_EMIT opened(m_wallet_model);

src/qt/walletcontroller.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#include <qt/sendcoinsrecipient.h>
99
#include <support/allocators/secure.h>
1010
#include <sync.h>
11+
#include <util/translation.h>
1112

1213
#include <map>
1314
#include <memory>
@@ -104,8 +105,8 @@ class WalletControllerActivity : public QObject
104105
QWidget* const m_parent_widget;
105106
QProgressDialog* m_progress_dialog{nullptr};
106107
WalletModel* m_wallet_model{nullptr};
107-
std::string m_error_message;
108-
std::vector<std::string> m_warning_message;
108+
bilingual_str m_error_message;
109+
std::vector<bilingual_str> m_warning_message;
109110
};
110111

111112

src/util/translation.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,20 @@ struct bilingual_str {
1818
std::string translated;
1919
};
2020

21+
inline bilingual_str operator+(const bilingual_str& lhs, const bilingual_str& rhs)
22+
{
23+
return bilingual_str{
24+
lhs.original + rhs.original,
25+
lhs.translated + rhs.translated};
26+
}
27+
28+
/** Mark a bilingual_str as untranslated */
29+
inline static bilingual_str Untranslated(std::string original) { return {original, original}; }
30+
/** Unary operator to return the original */
31+
inline static std::string OpOriginal(const bilingual_str& b) { return b.original; }
32+
/** Unary operator to return the translation */
33+
inline static std::string OpTranslated(const bilingual_str& b) { return b.translated; }
34+
2135
namespace tinyformat {
2236
template <typename... Args>
2337
bilingual_str format(const bilingual_str& fmt, const Args&... args)

src/wallet/db.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -393,7 +393,7 @@ bool BerkeleyBatch::Recover(const fs::path& file_path, void *callbackDataIn, boo
393393
return fSuccess;
394394
}
395395

396-
bool BerkeleyBatch::VerifyEnvironment(const fs::path& file_path, std::string& errorStr)
396+
bool BerkeleyBatch::VerifyEnvironment(const fs::path& file_path, bilingual_str& errorStr)
397397
{
398398
std::string walletFile;
399399
std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(file_path, walletFile);
@@ -403,14 +403,14 @@ bool BerkeleyBatch::VerifyEnvironment(const fs::path& file_path, std::string& er
403403
LogPrintf("Using wallet %s\n", file_path.string());
404404

405405
if (!env->Open(true /* retry */)) {
406-
errorStr = strprintf(_("Error initializing wallet database environment %s!").translated, walletDir);
406+
errorStr = strprintf(_("Error initializing wallet database environment %s!"), walletDir);
407407
return false;
408408
}
409409

410410
return true;
411411
}
412412

413-
bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::vector<std::string>& warnings, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc)
413+
bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::vector<bilingual_str>& warnings, bilingual_str& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc)
414414
{
415415
std::string walletFile;
416416
std::shared_ptr<BerkeleyEnvironment> env = GetWalletEnv(file_path, walletFile);
@@ -425,12 +425,12 @@ bool BerkeleyBatch::VerifyDatabaseFile(const fs::path& file_path, std::vector<st
425425
warnings.push_back(strprintf(_("Warning: Wallet file corrupt, data salvaged!"
426426
" Original %s saved as %s in %s; if"
427427
" your balance or transactions are incorrect you should"
428-
" restore from a backup.").translated,
428+
" restore from a backup."),
429429
walletFile, backup_filename, walletDir));
430430
}
431431
if (r == BerkeleyEnvironment::VerifyResult::RECOVER_FAIL)
432432
{
433-
errorStr = strprintf(_("%s corrupt, salvage failed").translated, walletFile);
433+
errorStr = strprintf(_("%s corrupt, salvage failed"), walletFile);
434434
return false;
435435
}
436436
}

src/wallet/db.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
#include <db_cxx.h>
2323

24+
struct bilingual_str;
25+
2426
static const unsigned int DEFAULT_WALLET_DBLOGSIZE = 100;
2527
static const bool DEFAULT_WALLET_PRIVDB = true;
2628

@@ -242,9 +244,9 @@ class BerkeleyBatch
242244
ideal to be called periodically */
243245
static bool PeriodicFlush(BerkeleyDatabase& database);
244246
/* verifies the database environment */
245-
static bool VerifyEnvironment(const fs::path& file_path, std::string& errorStr);
247+
static bool VerifyEnvironment(const fs::path& file_path, bilingual_str& errorStr);
246248
/* verifies the database file */
247-
static bool VerifyDatabaseFile(const fs::path& file_path, std::vector<std::string>& warnings, std::string& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc);
249+
static bool VerifyDatabaseFile(const fs::path& file_path, std::vector<bilingual_str>& warnings, bilingual_str& errorStr, BerkeleyEnvironment::recoverFunc_type recoverFunc);
248250

249251
template <typename K, typename T>
250252
bool Read(const K& key, T& value)

src/wallet/load.cpp

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,14 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wal
5353
return false;
5454
}
5555

56-
std::string error_string;
57-
std::vector<std::string> warnings;
56+
bilingual_str error_string;
57+
std::vector<bilingual_str> warnings;
5858
bool verify_success = CWallet::Verify(chain, location, salvage_wallet, error_string, warnings);
59-
if (!error_string.empty()) chain.initError(error_string);
60-
if (!warnings.empty()) chain.initWarning(Join(warnings, "\n"));
61-
if (!verify_success) return false;
59+
if (!warnings.empty()) chain.initWarning(Join(warnings, "\n", OpTranslated));
60+
if (!verify_success) {
61+
chain.initError(error_string.translated);
62+
return false;
63+
}
6264
}
6365

6466
return true;
@@ -68,12 +70,12 @@ bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& walle
6870
{
6971
try {
7072
for (const std::string& walletFile : wallet_files) {
71-
std::string error;
72-
std::vector<std::string> warnings;
73+
bilingual_str error;
74+
std::vector<bilingual_str> warnings;
7375
std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile), error, warnings);
74-
if (!warnings.empty()) chain.initWarning(Join(warnings, "\n"));
76+
if (!warnings.empty()) chain.initWarning(Join(warnings, "\n", OpTranslated));
7577
if (!pwallet) {
76-
chain.initError(error);
78+
chain.initError(error.translated);
7779
return false;
7880
}
7981
AddWallet(pwallet);

src/wallet/rpcwallet.cpp

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include <util/moneystr.h>
2424
#include <util/string.h>
2525
#include <util/system.h>
26+
#include <util/translation.h>
2627
#include <util/url.h>
2728
#include <util/vector.h>
2829
#include <wallet/coincontrol.h>
@@ -2589,14 +2590,14 @@ static UniValue loadwallet(const JSONRPCRequest& request)
25892590
}
25902591
}
25912592

2592-
std::string error;
2593-
std::vector<std::string> warning;
2594-
std::shared_ptr<CWallet> const wallet = LoadWallet(*g_rpc_chain, location, error, warning);
2595-
if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error);
2593+
bilingual_str error;
2594+
std::vector<bilingual_str> warnings;
2595+
std::shared_ptr<CWallet> const wallet = LoadWallet(*g_rpc_chain, location, error, warnings);
2596+
if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error.original);
25962597

25972598
UniValue obj(UniValue::VOBJ);
25982599
obj.pushKV("name", wallet->GetName());
2599-
obj.pushKV("warning", Join(warning, "\n"));
2600+
obj.pushKV("warning", Join(warnings, "\n", OpOriginal));
26002601

26012602
return obj;
26022603
}
@@ -2705,12 +2706,12 @@ static UniValue createwallet(const JSONRPCRequest& request)
27052706
}
27062707
SecureString passphrase;
27072708
passphrase.reserve(100);
2708-
std::vector<std::string> warnings;
2709+
std::vector<bilingual_str> warnings;
27092710
if (!request.params[3].isNull()) {
27102711
passphrase = request.params[3].get_str().c_str();
27112712
if (passphrase.empty()) {
27122713
// Empty string means unencrypted
2713-
warnings.emplace_back("Empty string given as passphrase, wallet will not be encrypted.");
2714+
warnings.emplace_back(Untranslated("Empty string given as passphrase, wallet will not be encrypted."));
27142715
}
27152716
}
27162717

@@ -2721,22 +2722,22 @@ static UniValue createwallet(const JSONRPCRequest& request)
27212722
flags |= WALLET_FLAG_DESCRIPTORS;
27222723
}
27232724

2724-
std::string error;
2725+
bilingual_str error;
27252726
std::shared_ptr<CWallet> wallet;
27262727
WalletCreationStatus status = CreateWallet(*g_rpc_chain, passphrase, flags, request.params[0].get_str(), error, warnings, wallet);
27272728
switch (status) {
27282729
case WalletCreationStatus::CREATION_FAILED:
2729-
throw JSONRPCError(RPC_WALLET_ERROR, error);
2730+
throw JSONRPCError(RPC_WALLET_ERROR, error.original);
27302731
case WalletCreationStatus::ENCRYPTION_FAILED:
2731-
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, error);
2732+
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, error.original);
27322733
case WalletCreationStatus::SUCCESS:
27332734
break;
27342735
// no default case, so the compiler can warn about missing cases
27352736
}
27362737

27372738
UniValue obj(UniValue::VOBJ);
27382739
obj.pushKV("name", wallet->GetName());
2739-
obj.pushKV("warning", Join(warnings, "\n"));
2740+
obj.pushKV("warning", Join(warnings, "\n", OpOriginal));
27402741

27412742
return obj;
27422743
}
@@ -4239,12 +4240,12 @@ static UniValue upgradewallet(const JSONRPCRequest& request)
42394240
version = request.params[0].get_int();
42404241
}
42414242

4242-
std::string error;
4243-
std::vector<std::string> warnings;
4243+
bilingual_str error;
4244+
std::vector<bilingual_str> warnings;
42444245
if (!pwallet->UpgradeWallet(version, error, warnings)) {
4245-
throw JSONRPCError(RPC_WALLET_ERROR, error);
4246+
throw JSONRPCError(RPC_WALLET_ERROR, error.original);
42464247
}
4247-
return error;
4248+
return error.original;
42484249
}
42494250

42504251
UniValue abortrescan(const JSONRPCRequest& request); // in rpcdump.cpp

0 commit comments

Comments
 (0)