Merge pull request #4735 from kittywhiskers/translation

merge bitcoin#16244...18699: translation backports
This commit is contained in:
UdjinM6 2022-04-07 13:18:29 +03:00 committed by GitHub
commit 903291788c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
81 changed files with 1282 additions and 664 deletions

View File

@ -19,7 +19,8 @@ FORMS += \
../src/qt/forms/sendcoinsdialog.ui \
../src/qt/forms/sendcoinsentry.ui \
../src/qt/forms/signverifymessagedialog.ui \
../src/qt/forms/transactiondescdialog.ui
../src/qt/forms/transactiondescdialog.ui \
../src/qt/forms/createwalletdialog.ui
RESOURCES += \
../src/qt/dash.qrc

View File

@ -0,0 +1,4 @@
RPC changes
-----------
`createwallet` now returns a warning if an empty string is used as an encryption password, and does not encrypt the wallet, instead of raising an error.
This makes it easier to disable encryption but also specify other options when using the `bitcoin-cli` tool.

View File

@ -311,6 +311,7 @@ BITCOIN_CORE_H = \
util/string.h \
util/time.h \
util/threadnames.h \
util/translation.h \
util/vector.h \
util/url.h \
util/validation.h \

View File

@ -14,6 +14,7 @@ QT_FORMS_UI = \
qt/forms/appearancewidget.ui \
qt/forms/askpassphrasedialog.ui \
qt/forms/coincontroldialog.ui \
qt/forms/createwalletdialog.ui \
qt/forms/editaddressdialog.ui \
qt/forms/governancelist.ui \
qt/forms/helpmessagedialog.ui \
@ -37,6 +38,7 @@ QT_MOC_CPP = \
qt/moc_addresstablemodel.cpp \
qt/moc_appearancewidget.cpp \
qt/moc_askpassphrasedialog.cpp \
qt/moc_createwalletdialog.cpp \
qt/moc_bantablemodel.cpp \
qt/moc_bitcoinaddressvalidator.cpp \
qt/moc_bitcoinamountfield.cpp \
@ -125,6 +127,7 @@ BITCOIN_QT_H = \
qt/clientmodel.h \
qt/coincontroldialog.h \
qt/coincontroltreewidget.h \
qt/createwalletdialog.h \
qt/csvmodelwriter.h \
qt/dash.h \
qt/editaddressdialog.h \
@ -240,6 +243,7 @@ BITCOIN_QT_WALLET_CPP = \
qt/askpassphrasedialog.cpp \
qt/coincontroldialog.cpp \
qt/coincontroltreewidget.cpp \
qt/createwalletdialog.cpp \
qt/editaddressdialog.cpp \
qt/governancelist.cpp \
qt/masternodelist.cpp \

View File

@ -9,12 +9,13 @@
#include <ui_interface.h>
#include <util/system.h>
#include <util/time.h>
#include <util/translation.h>
BanMan::BanMan(fs::path ban_file, CClientUIInterface* client_interface, int64_t default_ban_time)
: m_client_interface(client_interface), m_ban_db(std::move(ban_file)), m_default_ban_time(default_ban_time)
{
if (m_client_interface) m_client_interface->InitMessage(_("Loading banlist..."));
if (m_client_interface) m_client_interface->InitMessage(_("Loading banlist...").translated);
int64_t n_start = GetTimeMillis();
m_is_dirty = false;

View File

@ -45,7 +45,7 @@ int main(int argc, char** argv)
SetupBenchArgs();
std::string error;
if (!gArgs.ParseParameters(argc, argv, error)) {
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error.c_str());
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error);
return EXIT_FAILURE;
}

View File

@ -18,6 +18,7 @@
#include <util/moneystr.h>
#include <util/ranges.h>
#include <util/system.h>
#include <util/translation.h>
#include <validation.h>
#include <version.h>
#include <wallet/coincontrol.h>
@ -228,7 +229,7 @@ void CCoinJoinClientSession::ProcessMessage(CNode* pfrom, const std::string& str
return;
}
LogPrint(BCLog::COINJOIN, "DSCOMPLETE -- nMsgSessionID %d nMsgMessageID %d (%s)\n", nMsgSessionID, nMsgMessageID, CCoinJoin::GetMessageByID(nMsgMessageID));
LogPrint(BCLog::COINJOIN, "DSCOMPLETE -- nMsgSessionID %d nMsgMessageID %d (%s)\n", nMsgSessionID, nMsgMessageID, CCoinJoin::GetMessageByID(nMsgMessageID).translated);
CompletedTransaction(nMsgMessageID);
}
@ -297,7 +298,7 @@ void CCoinJoinClientSession::UnlockCoins()
vecOutPointLocked.clear();
}
std::string CCoinJoinClientSession::GetStatus(bool fWaitForBlock) const
bilingual_str CCoinJoinClientSession::GetStatus(bool fWaitForBlock) const
{
static int nStatusMessageProgress = 0;
nStatusMessageProgress += 10;
@ -331,20 +332,20 @@ std::string CCoinJoinClientSession::GetStatus(bool fWaitForBlock) const
strSuffix = "...";
return strprintf(_("Found enough users, signing ( waiting %s )"), strSuffix);
case POOL_STATE_ERROR:
return strprintf(_("%s request incomplete: %s"), gCoinJoinName, strLastMessage) + " " + _("Will retry...");
return strprintf(_("%s request incomplete:"), gCoinJoinName) + strLastMessage + Untranslated(" ") + _("Will retry...");
default:
return strprintf(_("Unknown state: id = %u"), nState);
}
}
std::string CCoinJoinClientManager::GetStatuses()
bilingual_str CCoinJoinClientManager::GetStatuses()
{
std::string strStatus;
bilingual_str strStatus;
bool fWaitForBlock = WaitForAnotherBlock();
LOCK(cs_deqsessions);
for (const auto& session : deqSessions) {
strStatus += session.GetStatus(fWaitForBlock) + "; ";
strStatus = strStatus + session.GetStatus(fWaitForBlock) + Untranslated("; ");
}
return strStatus;
}
@ -466,7 +467,7 @@ bool CCoinJoinClientSession::SendDenominate(const std::vector<std::pair<CTxDSIn,
}
SetState(POOL_STATE_ACCEPTING_ENTRIES);
strLastMessage = "";
strLastMessage = Untranslated("");
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::SendDenominate -- Added transaction to pool.\n");
@ -510,12 +511,12 @@ void CCoinJoinClientSession::ProcessPoolStateUpdate(CCoinJoinStatusUpdate psssup
return;
}
std::string strMessageTmp = CCoinJoin::GetMessageByID(psssup.nMessageID);
strAutoDenomResult = _("Masternode:") + " " + strMessageTmp;
bilingual_str strMessageTmp = CCoinJoin::GetMessageByID(psssup.nMessageID);
strAutoDenomResult = _("Masternode:") + Untranslated(" ") + strMessageTmp;
switch (psssup.nStatusUpdate) {
case STATUS_REJECTED: {
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- rejected by Masternode: %s\n", __func__, strMessageTmp);
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- rejected by Masternode: %s\n", __func__, strMessageTmp.translated);
SetState(POOL_STATE_ERROR);
UnlockCoins();
keyHolderStorage.ReturnAll();
@ -528,9 +529,9 @@ void CCoinJoinClientSession::ProcessPoolStateUpdate(CCoinJoinStatusUpdate psssup
// new session id should be set only in POOL_STATE_QUEUE state
nSessionID = psssup.nSessionID;
nTimeLastSuccessfulStep = GetTime();
strMessageTmp += strprintf(" Set nSessionID to %d.", nSessionID);
strMessageTmp = strMessageTmp + strprintf(Untranslated(" Set nSessionID to %d."), nSessionID);
}
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- accepted by Masternode: %s\n", __func__, strMessageTmp);
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- accepted by Masternode: %s\n", __func__, strMessageTmp.translated);
break;
}
default: {
@ -576,7 +577,7 @@ bool CCoinJoinClientSession::SignFinalTransaction(const CTransaction& finalTrans
// Make sure all inputs/outputs are valid
PoolMessage nMessageID{MSG_NOERR};
if (!IsValidInOuts(finalMutableTransaction.vin, finalMutableTransaction.vout, nMessageID, nullptr)) {
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- ERROR! IsValidInOuts() failed: %s\n", __func__, CCoinJoin::GetMessageByID(nMessageID));
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- ERROR! IsValidInOuts() failed: %s\n", __func__, CCoinJoin::GetMessageByID(nMessageID).translated);
UnlockCoins();
keyHolderStorage.ReturnAll();
SetNull();
@ -698,8 +699,8 @@ bool CCoinJoinClientManager::CheckAutomaticBackup()
switch (nWalletBackups) {
case 0:
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- Automatic backups disabled, no mixing available.\n");
strAutoDenomResult = _("Automatic backups disabled") + ", " + _("no mixing available.");
strAutoDenomResult = _("Automatic backups disabled") + Untranslated(", ") + _("no mixing available.");
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original);
StopMixing();
mixingWallet.nKeysLeftSinceAutoBackup = 0; // no backup, no "keys since last backup"
return false;
@ -707,44 +708,44 @@ bool CCoinJoinClientManager::CheckAutomaticBackup()
// Automatic backup failed, nothing else we can do until user fixes the issue manually.
// There is no way to bring user attention in daemon mode, so we just update status and
// keep spamming if debug is on.
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- ERROR! Failed to create automatic backup.\n");
strAutoDenomResult = _("ERROR! Failed to create automatic backup") + ", " + _("see debug.log for details.");
strAutoDenomResult = _("ERROR! Failed to create automatic backup") + Untranslated(", ") + _("see debug.log for details.");
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original);
return false;
case -2:
// We were able to create automatic backup but keypool was not replenished because wallet is locked.
// There is no way to bring user attention in daemon mode, so we just update status and
// keep spamming if debug is on.
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- WARNING! Failed to create replenish keypool, please unlock your wallet to do so.\n");
strAutoDenomResult = _("WARNING! Failed to replenish keypool, please unlock your wallet to do so.") + ", " + _("see debug.log for details.");
strAutoDenomResult = _("WARNING! Failed to replenish keypool, please unlock your wallet to do so.") + Untranslated(", ") + _("see debug.log for details.");
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original);
return false;
}
if (mixingWallet.nKeysLeftSinceAutoBackup < COINJOIN_KEYS_THRESHOLD_STOP) {
// We should never get here via mixing itself but probably something else is still actively using keypool
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- Very low number of keys left: %d, no mixing available.\n", mixingWallet.nKeysLeftSinceAutoBackup);
strAutoDenomResult = strprintf(_("Very low number of keys left: %d") + ", " + _("no mixing available."), mixingWallet.nKeysLeftSinceAutoBackup);
strAutoDenomResult = strprintf(_("Very low number of keys left: %d") + Untranslated(", ") + _("no mixing available."), mixingWallet.nKeysLeftSinceAutoBackup);
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original);
// It's getting really dangerous, stop mixing
StopMixing();
return false;
} else if (mixingWallet.nKeysLeftSinceAutoBackup < COINJOIN_KEYS_THRESHOLD_WARNING) {
// Low number of keys left, but it's still more or less safe to continue
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- Very low number of keys left: %d\n", mixingWallet.nKeysLeftSinceAutoBackup);
strAutoDenomResult = strprintf(_("Very low number of keys left: %d"), mixingWallet.nKeysLeftSinceAutoBackup);
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original);
if (fCreateAutoBackups) {
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- Trying to create new backup.\n");
std::string warningString;
std::string errorString;
bilingual_str errorString;
std::vector<bilingual_str> warnings;
if (!mixingWallet.AutoBackupWallet("", warningString, errorString)) {
if (!warningString.empty()) {
if (!mixingWallet.AutoBackupWallet("", errorString, warnings)) {
if (!warnings.empty()) {
// There were some issues saving backup but yet more or less safe to continue
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- WARNING! Something went wrong on automatic backup: %s\n", warningString);
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- WARNING! Something went wrong on automatic backup: %s\n", Join(warnings, "\n", OpTranslated));
}
if (!errorString.empty()) {
if (!errorString.original.empty()) {
// Things are really broken
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- ERROR! Failed to create automatic backup: %s\n", errorString);
strAutoDenomResult = strprintf(_("ERROR! Failed to create automatic backup") + ": %s", errorString);
strAutoDenomResult = _("ERROR! Failed to create automatic backup") + Untranslated(": ") + errorString;
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::CheckAutomaticBackup -- %s\n", strAutoDenomResult.original);
return false;
}
}
@ -797,8 +798,8 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, bool fDr
if (deterministicMNManager->GetListAtChainTip().GetValidMNsCount() == 0 &&
Params().NetworkIDString() != CBaseChainParams::REGTEST) {
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::DoAutomaticDenominating -- No Masternodes detected\n");
strAutoDenomResult = _("No Masternodes detected.");
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original);
return false;
}
@ -827,8 +828,8 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, bool fDr
// mixable balance is way too small
if (nBalanceAnonymizable < nValueMin) {
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::DoAutomaticDenominating -- Not enough funds to mix\n");
strAutoDenomResult = _("Not enough funds to mix.");
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original);
return false;
}
@ -902,8 +903,8 @@ bool CCoinJoinClientSession::DoAutomaticDenominating(CConnman& connman, bool fDr
// should be no unconfirmed denoms in non-multi-session mode
if (!CCoinJoinClientOptions::IsMultiSessionEnabled() && nBalanceDenominatedUnconf > 0) {
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::DoAutomaticDenominating -- Found unconfirmed denominated outputs, will wait till they confirm to continue.\n");
strAutoDenomResult = _("Found unconfirmed denominated outputs, will wait till they confirm to continue.");
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original);
return false;
}
@ -978,8 +979,8 @@ bool CCoinJoinClientManager::DoAutomaticDenominating(CConnman& connman, bool fDr
if (!CheckAutomaticBackup()) return false;
if (WaitForAnotherBlock()) {
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::DoAutomaticDenominating -- Last successful action was too recent\n");
strAutoDenomResult = _("Last successful action was too recent.");
LogPrint(BCLog::COINJOIN, "CCoinJoinClientManager::DoAutomaticDenominating -- %s\n", strAutoDenomResult.original);
return false;
}
@ -1110,8 +1111,8 @@ bool CCoinJoinClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CCon
std::set<CAmount> setAmounts;
if (!mixingWallet.SelectDenominatedAmounts(nBalanceNeedsAnonymized, setAmounts)) {
// this should never happen
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::StartNewQueue -- Can't mix: no compatible inputs found!\n");
strAutoDenomResult = _("Can't mix: no compatible inputs found!");
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::StartNewQueue -- %s\n", strAutoDenomResult.original);
return false;
}
@ -1120,8 +1121,8 @@ bool CCoinJoinClientSession::StartNewQueue(CAmount nBalanceNeedsAnonymized, CCon
auto dmn = coinJoinClientManagers.at(mixingWallet.GetName())->GetRandomNotUsedMasternode();
if (!dmn) {
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::StartNewQueue -- Can't find random masternode!\n");
strAutoDenomResult = _("Can't find random Masternode.");
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::StartNewQueue -- %s\n", strAutoDenomResult.original);
return false;
}
@ -1285,7 +1286,7 @@ bool CCoinJoinClientSession::SubmitDenominate(CConnman& connman)
// Should never actually get here but just in case
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::SubmitDenominate -- Running CoinJoin denominate for all rounds, error: %s\n", strError);
strAutoDenomResult = strError;
strAutoDenomResult = Untranslated(strError);
return false;
}
@ -1497,15 +1498,15 @@ bool CCoinJoinClientSession::MakeCollateralAmounts(const CompactTallyItem& tally
assert(txBuilder.IsDust(txBuilder.GetAmountLeft()));
std::string strResult;
bilingual_str strResult;
if (!txBuilder.Commit(strResult)) {
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- Commit failed: %s\n", __func__, strResult);
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- Commit failed: %s\n", __func__, strResult.original);
return false;
}
coinJoinClientManagers.at(mixingWallet.GetName())->UpdatedSuccessBlock();
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- txid: %s\n", __func__, strResult);
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- txid: %s\n", __func__, strResult.original);
return true;
}
@ -1774,16 +1775,16 @@ bool CCoinJoinClientSession::CreateDenominated(CAmount nBalanceToDenominate, con
return false;
}
std::string strResult;
bilingual_str strResult;
if (!txBuilder.Commit(strResult)) {
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- Commit failed: %s\n", __func__, strResult);
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- Commit failed: %s\n", __func__, strResult.original);
return false;
}
// use the same nCachedLastSuccessBlock as for DS mixing to prevent race
coinJoinClientManagers.at(mixingWallet.GetName())->UpdatedSuccessBlock();
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- txid: %s\n", __func__, strResult);
LogPrint(BCLog::COINJOIN, "CCoinJoinClientSession::%s -- txid: %s\n", __func__, strResult.original);
return true;
}

View File

@ -7,6 +7,7 @@
#include <coinjoin/util.h>
#include <coinjoin/coinjoin.h>
#include <util/translation.h>
#include <utility>
#include <atomic>
@ -71,8 +72,8 @@ class CCoinJoinClientSession : public CCoinJoinBaseSession
private:
std::vector<COutPoint> vecOutPointLocked;
std::string strLastMessage;
std::string strAutoDenomResult;
bilingual_str strLastMessage;
bilingual_str strAutoDenomResult;
CDeterministicMNCPtr mixingMasternode;
CMutableTransaction txMyCollateral; // client side collateral
@ -128,7 +129,7 @@ public:
void ResetPool();
std::string GetStatus(bool fWaitForBlock) const;
bilingual_str GetStatus(bool fWaitForBlock) const;
bool GetMixingMasternodeInfo(CDeterministicMNCPtr& ret) const;
@ -171,7 +172,7 @@ private:
int nCachedLastSuccessBlock{0};
int nMinBlocksToWait{1}; // how many blocks to wait for after one successful mixing tx in non-multisession mode
std::string strAutoDenomResult;
bilingual_str strAutoDenomResult;
CWallet& mixingWallet;
@ -201,7 +202,7 @@ public:
bool IsMixing() const;
void ResetPool();
std::string GetStatuses();
bilingual_str GetStatuses();
std::string GetSessionDenoms();
bool GetMixingMasternodesInfo(std::vector<CDeterministicMNCPtr>& vecDmnsRet) const;

View File

@ -17,6 +17,7 @@
#include <txmempool.h>
#include <util/moneystr.h>
#include <util/system.h>
#include <util/translation.h>
#include <validation.h>
#include <string>
@ -374,7 +375,7 @@ std::string CCoinJoin::DenominationToString(int nDenom)
return "to-string-error";
}
std::string CCoinJoin::GetMessageByID(PoolMessage nMessageID)
bilingual_str CCoinJoin::GetMessageByID(PoolMessage nMessageID)
{
switch (nMessageID) {
case ERR_ALREADY_HAVE:

View File

@ -14,6 +14,7 @@
#include <tinyformat.h>
#include <univalue.h>
#include <util/ranges.h>
#include <util/translation.h>
#include <utility>
@ -440,7 +441,7 @@ public:
*/
static std::string DenominationToString(int nDenom);
static std::string GetMessageByID(PoolMessage nMessageID);
static bilingual_str GetMessageByID(PoolMessage nMessageID);
/// Get the minimum/maximum number of participants for the pool
static int GetMinPoolParticipants();

View File

@ -625,7 +625,7 @@ bool CCoinJoinServer::AddEntry(CConnman& connman, const CCoinJoinEntry& entry, P
bool fConsumeCollateral{false};
if (!IsValidInOuts(vin, entry.vecTxOut, nMessageIDRet, &fConsumeCollateral)) {
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- ERROR! IsValidInOuts() failed: %s\n", __func__, CCoinJoin::GetMessageByID(nMessageIDRet));
LogPrint(BCLog::COINJOIN, "CCoinJoinServer::%s -- ERROR! IsValidInOuts() failed: %s\n", __func__, CCoinJoin::GetMessageByID(nMessageIDRet).translated);
if (fConsumeCollateral) {
ConsumeCollateral(connman, entry.txCollateral);
}

View File

@ -10,6 +10,7 @@
#include <validation.h>
#include <wallet/fees.h>
#include <wallet/wallet.h>
#include <util/translation.h>
#include <numeric>
@ -254,7 +255,7 @@ bool CTransactionBuilder::IsDust(CAmount nAmount) const
return ::IsDust(CTxOut(nAmount, ::GetScriptForDestination(tallyItem.txdest)), coinControl.m_discard_feerate.get());
}
bool CTransactionBuilder::Commit(std::string& strResult)
bool CTransactionBuilder::Commit(bilingual_str& strResult)
{
CAmount nFeeRet = 0;
int nChangePosRet = -1;
@ -278,13 +279,13 @@ bool CTransactionBuilder::Commit(std::string& strResult)
bool fDust = IsDust(nAmountLeft);
// If there is a either remainder which is considered to be dust (will be added to fee in this case) or no amount left there should be no change output, return if there is a change output.
if (nChangePosRet != -1 && fDust) {
strResult = strprintf("Unexpected change output %s at position %d", tx->vout[nChangePosRet].ToString(), nChangePosRet);
strResult = Untranslated(strprintf("Unexpected change output %s at position %d", tx->vout[nChangePosRet].ToString(), nChangePosRet));
return false;
}
// If there is a remainder which is not considered to be dust it should end up in a change output, return if not.
if (nChangePosRet == -1 && !fDust) {
strResult = strprintf("Change output missing: %d", nAmountLeft);
strResult = Untranslated(strprintf("Change output missing: %d", nAmountLeft));
return false;
}
@ -301,7 +302,7 @@ bool CTransactionBuilder::Commit(std::string& strResult)
// If the calculated fee does not match the fee returned by CreateTransaction aka if this check fails something is wrong!
CAmount nFeeCalc = GetFee(GetBytesTotal() + nBytesAdditional) + nFeeAdditional;
if (nFeeRet != nFeeCalc) {
strResult = strprintf("Fee validation failed -> nFeeRet: %d, nFeeCalc: %d, nFeeAdditional: %d, nBytesAdditional: %d, %s", nFeeRet, nFeeCalc, nFeeAdditional, nBytesAdditional, ToString());
strResult = Untranslated(strprintf("Fee validation failed -> nFeeRet: %d, nFeeCalc: %d, nFeeAdditional: %d, nBytesAdditional: %d, %s", nFeeRet, nFeeCalc, nFeeAdditional, nBytesAdditional, ToString()));
return false;
}
@ -309,7 +310,7 @@ bool CTransactionBuilder::Commit(std::string& strResult)
fKeepKeys = true;
strResult = tx->GetHash().ToString();
strResult = Untranslated(tx->GetHash().ToString());
return true;
}

View File

@ -8,6 +8,7 @@
#include <wallet/wallet.h>
class CTransactionBuilder;
struct bilingual_str;
class CKeyHolder
{
@ -116,7 +117,7 @@ public:
/// Get the total number of added outputs
int CountOutputs() const { LOCK(cs_outputs); return vecOutputs.size(); }
/// Create and Commit the transaction to the wallet
bool Commit(std::string& strResult);
bool Commit(bilingual_str& strResult);
/// Convert to a string
std::string ToString() const;

View File

@ -9,7 +9,7 @@
CHKDF_HMAC_SHA256_L32::CHKDF_HMAC_SHA256_L32(const unsigned char* ikm, size_t ikmlen, const std::string& salt)
{
CHMAC_SHA256((const unsigned char*)salt.c_str(), salt.size()).Write(ikm, ikmlen).Finalize(m_prk);
CHMAC_SHA256((const unsigned char*)salt.data(), salt.size()).Write(ikm, ikmlen).Finalize(m_prk);
}
void CHKDF_HMAC_SHA256_L32::Expand32(const std::string& info, unsigned char hash[OUTPUT_SIZE])

View File

@ -14,9 +14,11 @@
#include <rpc/protocol.h>
#include <rpc/request.h>
#include <stacktraces.h>
#include <util/system.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
#include <functional>
#include <memory>
#include <stdio.h>
#include <tuple>
@ -109,7 +111,7 @@ static int AppInitRPC(int argc, char* argv[])
SetupCliArgs();
std::string error;
if (!gArgs.ParseParameters(argc, argv, error)) {
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error.c_str());
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error);
return EXIT_FAILURE;
}
@ -129,7 +131,7 @@ static int AppInitRPC(int argc, char* argv[])
strUsage += "\n" + gArgs.GetHelpMessage();
}
tfm::format(std::cout, "%s", strUsage.c_str());
tfm::format(std::cout, "%s", strUsage);
if (argc < 2) {
tfm::format(std::cerr, "Error: too few parameters\n");
return EXIT_FAILURE;
@ -138,15 +140,15 @@ static int AppInitRPC(int argc, char* argv[])
}
bool datadirFromCmdLine = gArgs.IsArgSet("-datadir");
if (datadirFromCmdLine && !fs::is_directory(GetDataDir(false))) {
tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", ""));
return EXIT_FAILURE;
}
if (!gArgs.ReadConfigFiles(error, true)) {
tfm::format(std::cerr, "Error reading configuration file: %s\n", error.c_str());
tfm::format(std::cerr, "Error reading configuration file: %s\n", error);
return EXIT_FAILURE;
}
if (!datadirFromCmdLine && !fs::is_directory(GetDataDir(false))) {
tfm::format(std::cerr, "Error: Specified data directory \"%s\" from config file does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
tfm::format(std::cerr, "Error: Specified data directory \"%s\" from config file does not exist.\n", gArgs.GetArg("-datadir", ""));
return EXIT_FAILURE;
}
// Check for -testnet or -regtest parameter (BaseParams() calls are only valid after this clause)
@ -411,7 +413,7 @@ static UniValue CallRPC(BaseRequestHandler *rh, const std::string& strMethod, co
if (failedToGetAuthCookie) {
throw std::runtime_error(strprintf(
"Could not locate RPC credentials. No authentication cookie could be found, and RPC password is not set. See -rpcpassword and -stdinrpcpass. Configuration file: (%s)",
GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string().c_str()));
GetConfigFile(gArgs.GetArg("-conf", BITCOIN_CONF_FILENAME)).string()));
} else {
throw std::runtime_error("Authorization failed: Incorrect rpcuser or rpcpassword");
}
@ -559,7 +561,7 @@ static int CommandLineRPC(int argc, char *argv[])
}
if (strPrint != "") {
tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint.c_str());
tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint);
}
return nRet;
}

View File

@ -17,10 +17,12 @@
#include <script/script.h>
#include <script/sign.h>
#include <univalue.h>
#include <util/system.h>
#include <util/moneystr.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
#include <functional>
#include <memory>
#include <stdio.h>
@ -81,7 +83,7 @@ static int AppInitRawTx(int argc, char* argv[])
SetupBitcoinTxArgs();
std::string error;
if (!gArgs.ParseParameters(argc, argv, error)) {
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error.c_str());
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error);
return EXIT_FAILURE;
}
@ -108,7 +110,7 @@ static int AppInitRawTx(int argc, char* argv[])
"\n";
strUsage += gArgs.GetHelpMessage();
tfm::format(std::cout, "%s", strUsage.c_str());
tfm::format(std::cout, "%s", strUsage);
if (argc < 2) {
tfm::format(std::cerr, "Error: too few parameters\n");
@ -679,21 +681,21 @@ static void OutputTxJSON(const CTransaction& tx)
TxToUniv(tx, uint256(), entry);
std::string jsonOutput = entry.write(4);
tfm::format(std::cout, "%s\n", jsonOutput.c_str());
tfm::format(std::cout, "%s\n", jsonOutput);
}
static void OutputTxHash(const CTransaction& tx)
{
std::string strHexHash = tx.GetHash().GetHex(); // the hex-encoded transaction hash (aka the transaction id)
tfm::format(std::cout, "%s\n", strHexHash.c_str());
tfm::format(std::cout, "%s\n", strHexHash);
}
static void OutputTxHex(const CTransaction& tx)
{
std::string strHex = EncodeHexTx(tx);
tfm::format(std::cout, "%s\n", strHex.c_str());
tfm::format(std::cout, "%s\n", strHex);
}
static void OutputTx(const CTransaction& tx)
@ -784,7 +786,7 @@ static int CommandLineRawTx(int argc, char* argv[])
}
if (strPrint != "") {
tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint.c_str());
tfm::format(nRet == 0 ? std::cout : std::cerr, "%s\n", strPrint);
}
return nRet;
}

View File

@ -9,8 +9,9 @@
#include <chainparams.h>
#include <chainparamsbase.h>
#include <logging.h>
#include <util/system.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
#include <wallet/wallettool.h>
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;

View File

@ -15,11 +15,14 @@
#include <interfaces/chain.h>
#include <noui.h>
#include <shutdown.h>
#include <ui_interface.h>
#include <util/system.h>
#include <util/strencodings.h>
#include <util/threadnames.h>
#include <util/translation.h>
#include <stacktraces.h>
#include <functional>
#include <stdio.h>
const std::function<std::string(const char*)> G_TRANSLATION_FUN = nullptr;
@ -53,8 +56,7 @@ static bool AppInit(int argc, char* argv[])
SetupServerArgs();
std::string error;
if (!gArgs.ParseParameters(argc, argv, error)) {
tfm::format(std::cerr, "Error parsing command line arguments: %s\n", error.c_str());
return false;
return InitError(strprintf("Error parsing command line arguments: %s\n", error));
}
if (gArgs.IsArgSet("-printcrashinfo")) {
@ -76,7 +78,7 @@ static bool AppInit(int argc, char* argv[])
strUsage += "\n" + gArgs.GetHelpMessage();
}
tfm::format(std::cout, "%s", strUsage.c_str());
tfm::format(std::cout, "%s", strUsage);
return true;
}
@ -85,31 +87,27 @@ static bool AppInit(int argc, char* argv[])
bool datadirFromCmdLine = gArgs.IsArgSet("-datadir");
if (datadirFromCmdLine && !fs::is_directory(GetDataDir(false)))
{
tfm::format(std::cerr, "Error: Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
return false;
return InitError(strprintf("Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "")));
}
if (!gArgs.ReadConfigFiles(error, true)) {
tfm::format(std::cerr, "Error reading configuration file: %s\n", error.c_str());
return false;
return InitError(strprintf("Error reading configuration file: %s\n", error));
}
if (!datadirFromCmdLine && !fs::is_directory(GetDataDir(false)))
{
tfm::format(std::cerr, "Error: Specified data directory \"%s\" from config file does not exist.\n", gArgs.GetArg("-datadir", "").c_str());
tfm::format(std::cerr, "Error: Specified data directory \"%s\" from config file does not exist.\n", gArgs.GetArg("-datadir", ""));
return EXIT_FAILURE;
}
// Check for -testnet or -regtest parameter (Params() calls are only valid after this clause)
try {
SelectParams(gArgs.GetChainName());
} catch (const std::exception& e) {
tfm::format(std::cerr, "Error: %s\n", e.what());
return false;
return InitError(strprintf("%s\n", e.what()));
}
// Error out when loose non-argument tokens are encountered on command line
for (int i = 1; i < argc; i++) {
if (!IsSwitchChar(argv[i][0])) {
tfm::format(std::cerr, "Error: Command line contains unexpected token '%s', see dashd -h for a list of options.\n", argv[i]);
return false;
return InitError(strprintf("Command line contains unexpected token '%s', see dashd -h for a list of options.\n", argv[i]));
}
}
@ -140,19 +138,17 @@ static bool AppInit(int argc, char* argv[])
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
#endif
tfm::format(std::cout, "Dash Core server starting\n");
tfm::format(std::cout, PACKAGE_NAME "daemon starting\n");
// Daemonize
if (daemon(1, 0)) { // don't chdir (1), do close FDs (0)
tfm::format(std::cerr, "Error: daemon() failed: %s\n", strerror(errno));
return false;
return InitError(strprintf("daemon() failed: %s\n", strerror(errno)));
}
#if defined(MAC_OSX)
#pragma GCC diagnostic pop
#endif
#else
tfm::format(std::cerr, "Error: -daemon is not supported on this operating system\n");
return false;
return InitError("-daemon is not supported on this operating system\n");
#endif // HAVE_DECL_DAEMON
}
// Lock data directory after daemonization

View File

@ -5,8 +5,11 @@
#include <logging.h>
#include <util/system.h>
#include <walletinitinterface.h>
#include <support/allocators/secure.h>
class CWallet;
enum class WalletCreationStatus;
struct bilingual_str;
namespace interfaces {
class Chain;
@ -86,7 +89,12 @@ std::vector<std::shared_ptr<CWallet>> GetWallets()
throw std::logic_error("Wallet function called in non-wallet build.");
}
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning)
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings)
{
throw std::logic_error("Wallet function called in non-wallet build.");
}
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)
{
throw std::logic_error("Wallet function called in non-wallet build.");
}

View File

@ -133,10 +133,10 @@ std::string get_filesystem_error_message(const fs::filesystem_error& e)
#else
// Convert from Multi Byte to utf-16
std::string mb_string(e.what());
int size = MultiByteToWideChar(CP_ACP, 0, mb_string.c_str(), mb_string.size(), nullptr, 0);
int size = MultiByteToWideChar(CP_ACP, 0, mb_string.data(), mb_string.size(), nullptr, 0);
std::wstring utf16_string(size, L'\0');
MultiByteToWideChar(CP_ACP, 0, mb_string.c_str(), mb_string.size(), &*utf16_string.begin(), size);
MultiByteToWideChar(CP_ACP, 0, mb_string.data(), mb_string.size(), &*utf16_string.begin(), size);
// Convert from utf-16 to utf-8
return std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>, wchar_t>().to_bytes(utf16_string);
#endif

View File

@ -5,14 +5,15 @@
#include <httprpc.h>
#include <chainparams.h>
#include <crypto/hmac_sha256.h>
#include <httpserver.h>
#include <rpc/protocol.h>
#include <rpc/server.h>
#include <util/system.h>
#include <util/strencodings.h>
#include <ui_interface.h>
#include <util/strencodings.h>
#include <util/system.h>
#include <util/translation.h>
#include <walletinitinterface.h>
#include <crypto/hmac_sha256.h>
#include <memory>
@ -218,7 +219,7 @@ static bool InitRPCAuthentication()
LogPrintf("Using random cookie authentication.\n");
if (!GenerateAuthCookie(&strRPCUserColonPass)) {
uiInterface.ThreadSafeMessageBox(
_("Error: A fatal internal error occurred, see debug.log for details"), // Same message as AbortNode
_("Error: A fatal internal error occurred, see debug.log for details").translated, // Same message as AbortNode
"", CClientUIInterface::MSG_ERROR);
return false;
}

View File

@ -7,6 +7,7 @@
#include <shutdown.h>
#include <ui_interface.h>
#include <util/system.h>
#include <util/translation.h>
#include <validation.h>
#include <boost/thread.hpp>
@ -107,7 +108,7 @@ bool TxIndex::DB::MigrateData(CBlockTreeDB& block_tree_db, const CBlockLocator&
int64_t count = 0;
LogPrintf("Upgrading txindex database... [0%%]\n");
uiInterface.ShowProgress(_("Upgrading txindex database"), 0, true);
uiInterface.ShowProgress(_("Upgrading txindex database").translated, 0, true);
int report_done = 0;
const size_t batch_size = 1 << 24; // 16 MiB
@ -144,7 +145,7 @@ bool TxIndex::DB::MigrateData(CBlockTreeDB& block_tree_db, const CBlockLocator&
(static_cast<uint32_t>(*(txid.begin() + 1)) << 0);
int percentage_done = (int)(high_nibble * 100.0 / 65536.0 + 0.5);
uiInterface.ShowProgress(_("Upgrading txindex database"), percentage_done, true);
uiInterface.ShowProgress(_("Upgrading txindex database").translated, percentage_done, true);
if (report_done < percentage_done/10) {
LogPrintf("Upgrading txindex database... [%d%%]\n", percentage_done);
report_done = percentage_done/10;

View File

@ -30,32 +30,33 @@
#include <key.h>
#include <mapport.h>
#include <miner.h>
#include <netbase.h>
#include <net.h>
#include <net_permissions.h>
#include <net_processing.h>
#include <netbase.h>
#include <policy/feerate.h>
#include <policy/fees.h>
#include <policy/policy.h>
#include <policy/settings.h>
#include <rpc/server.h>
#include <rpc/register.h>
#include <rpc/blockchain.h>
#include <rpc/register.h>
#include <rpc/server.h>
#include <rpc/util.h>
#include <script/standard.h>
#include <script/sigcache.h>
#include <scheduler.h>
#include <script/sigcache.h>
#include <script/standard.h>
#include <shutdown.h>
#include <timedata.h>
#include <torcontrol.h>
#include <txdb.h>
#include <txmempool.h>
#include <torcontrol.h>
#include <ui_interface.h>
#include <util/asmap.h>
#include <util/error.h>
#include <util/moneystr.h>
#include <util/system.h>
#include <util/threadnames.h>
#include <util/translation.h>
#include <util/validation.h>
#include <validation.h>
#include <validationinterface.h>
@ -150,7 +151,7 @@ static fs::path GetPidFile()
tfm::format(file, "%d\n", getpid());
return true;
} else {
return InitError(strprintf(_("Unable to create the PID file '%s': %s"), GetPidFile().string(), std::strerror(errno)));
return InitError(strprintf(_("Unable to create the PID file '%s': %s").translated, GetPidFile().string(), std::strerror(errno)));
}
}
#endif
@ -755,20 +756,20 @@ std::string LicenseInfo()
const std::string URL_SOURCE_CODE = "<https://github.com/dashpay/dash>";
const std::string URL_WEBSITE = "<https://dash.org>";
return CopyrightHolders(_("Copyright (C)"), 2014, COPYRIGHT_YEAR) + "\n" +
return CopyrightHolders(_("Copyright (C)").translated, 2014, COPYRIGHT_YEAR) + "\n" +
"\n" +
strprintf(_("Please contribute if you find %s useful. "
"Visit %s for further information about the software."),
"Visit %s for further information about the software.").translated,
PACKAGE_NAME, URL_WEBSITE) +
"\n" +
strprintf(_("The source code is available from %s."),
strprintf(_("The source code is available from %s.").translated,
URL_SOURCE_CODE) +
"\n" +
"\n" +
_("This is experimental software.") + "\n" +
strprintf(_("Distributed under the MIT software license, see the accompanying file %s or %s"), "COPYING", "<https://opensource.org/licenses/MIT>") + "\n" +
_("This is experimental software.").translated + "\n" +
strprintf(_("Distributed under the MIT software license, see the accompanying file %s or %s").translated, "COPYING", "<https://opensource.org/licenses/MIT>") + "\n" +
"\n" +
strprintf(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard."), "<https://www.openssl.org>") +
strprintf(_("This product includes software developed by the OpenSSL Project for use in the OpenSSL Toolkit %s and cryptographic software written by Eric Young and UPnP software written by Thomas Bernard.").translated, "<https://www.openssl.org>") +
"\n";
}
@ -1164,11 +1165,6 @@ void InitParameterInteraction()
}
}
static std::string ResolveErrMsg(const char * const optname, const std::string& strBind)
{
return strprintf(_("Cannot resolve -%s address: '%s'"), optname, strBind);
}
/**
* Initialize global loggers.
*
@ -1272,16 +1268,16 @@ bool AppInitParameterInteraction()
// on the command line or in this network's section of the config file.
std::string network = gArgs.GetChainName();
for (const auto& arg : gArgs.GetUnsuitableSectionOnlyArgs()) {
return InitError(strprintf(_("Config setting for %s only applied on %s network when in [%s] section."), arg, network, network));
return InitError(strprintf(_("Config setting for %s only applied on %s network when in [%s] section.").translated, arg, network, network));
}
// Warn if unrecognized section name are present in the config file.
for (const auto& section : gArgs.GetUnrecognizedSections()) {
InitWarning(strprintf("%s:%i " + _("Section [%s] is not recognized."), section.m_file, section.m_line, section.m_name));
InitWarning(strprintf("%s:%i " + _("Section [%s] is not recognized.").translated, section.m_file, section.m_line, section.m_name));
}
if (!fs::is_directory(GetBlocksDir())) {
return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist."), gArgs.GetArg("-blocksdir", "").c_str()));
return InitError(strprintf(_("Specified blocks directory \"%s\" does not exist.").translated, gArgs.GetArg("-blocksdir", "")));
}
// parse and validate enabled filter types
@ -1293,7 +1289,7 @@ bool AppInitParameterInteraction()
for (const auto& name : names) {
BlockFilterType filter_type;
if (!BlockFilterTypeByName(name, filter_type)) {
return InitError(strprintf(_("Unknown -blockfilterindex value %s."), name));
return InitError(strprintf(_("Unknown -blockfilterindex value %s.").translated, name));
}
g_enabled_filter_types.insert(filter_type);
}
@ -1302,7 +1298,7 @@ bool AppInitParameterInteraction()
// Signal NODE_COMPACT_FILTERS if peerblockfilters and basic filters index are both enabled.
if (gArgs.GetBoolArg("-peerblockfilters", DEFAULT_PEERBLOCKFILTERS)) {
if (g_enabled_filter_types.count(BlockFilterType::BASIC_FILTER) != 1) {
return InitError(_("Cannot set -peerblockfilters without -blockfilterindex."));
return InitError(_("Cannot set -peerblockfilters without -blockfilterindex.").translated);
}
nLocalServices = ServiceFlags(nLocalServices | NODE_COMPACT_FILTERS);
@ -1311,25 +1307,25 @@ bool AppInitParameterInteraction()
// if using block pruning, then disallow txindex and require disabling governance validation
if (gArgs.GetArg("-prune", 0)) {
if (gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX))
return InitError(_("Prune mode is incompatible with -txindex."));
return InitError(_("Prune mode is incompatible with -txindex.").translated);
if (!gArgs.GetBoolArg("-disablegovernance", false)) {
return InitError(_("Prune mode is incompatible with -disablegovernance=false."));
return InitError(_("Prune mode is incompatible with -disablegovernance=false.").translated);
}
if (!g_enabled_filter_types.empty()) {
return InitError(_("Prune mode is incompatible with -blockfilterindex."));
return InitError(_("Prune mode is incompatible with -blockfilterindex.").translated);
}
}
if (gArgs.IsArgSet("-devnet")) {
// Require setting of ports when running devnet
if (gArgs.GetArg("-listen", DEFAULT_LISTEN) && !gArgs.IsArgSet("-port")) {
return InitError(_("-port must be specified when -devnet and -listen are specified"));
return InitError(_("-port must be specified when -devnet and -listen are specified").translated);
}
if (gArgs.GetArg("-server", false) && !gArgs.IsArgSet("-rpcport")) {
return InitError(_("-rpcport must be specified when -devnet and -server are specified"));
return InitError(_("-rpcport must be specified when -devnet and -server are specified").translated);
}
if (gArgs.GetArgs("-devnet").size() > 1) {
return InitError(_("-devnet can only be specified once"));
return InitError(_("-devnet can only be specified once").translated);
}
}
@ -1356,11 +1352,11 @@ bool AppInitParameterInteraction()
#endif
nMaxConnections = std::max(std::min<int>(nMaxConnections, fd_max - nBind - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS), 0);
if (nFD < MIN_CORE_FILEDESCRIPTORS)
return InitError(_("Not enough file descriptors available."));
return InitError(_("Not enough file descriptors available.").translated);
nMaxConnections = std::min(nFD - MIN_CORE_FILEDESCRIPTORS - MAX_ADDNODE_CONNECTIONS, nMaxConnections);
if (nMaxConnections < nUserMaxConnections)
InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations."), nUserMaxConnections, nMaxConnections));
InitWarning(strprintf(_("Reducing -maxconnections from %d to %d, because of system limitations.").translated, nUserMaxConnections, nMaxConnections));
// ********************************************************* Step 3: parameter-to-internal-flags
if (gArgs.IsArgSet("-debug")) {
@ -1371,7 +1367,7 @@ bool AppInitParameterInteraction()
[](std::string cat){return cat == "0" || cat == "none";})) {
for (const auto& cat : categories) {
if (!LogInstance().EnableCategory(cat)) {
InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debug", cat));
InitWarning(strprintf(_("Unsupported logging category %s=%s.").translated, "-debug", cat));
}
}
}
@ -1380,7 +1376,7 @@ bool AppInitParameterInteraction()
// Now remove the logging categories which were explicitly excluded
for (const std::string& cat : gArgs.GetArgs("-debugexclude")) {
if (!LogInstance().DisableCategory(cat)) {
InitWarning(strprintf(_("Unsupported logging category %s=%s."), "-debugexclude", cat));
InitWarning(strprintf(_("Unsupported logging category %s=%s.").translated, "-debugexclude", cat));
}
}
@ -1416,7 +1412,7 @@ bool AppInitParameterInteraction()
int64_t nMempoolSizeMax = gArgs.GetArg("-maxmempool", DEFAULT_MAX_MEMPOOL_SIZE) * 1000000;
int64_t nMempoolSizeMin = gArgs.GetArg("-limitdescendantsize", DEFAULT_DESCENDANT_SIZE_LIMIT) * 1000 * 40;
if (nMempoolSizeMax < 0 || nMempoolSizeMax < nMempoolSizeMin)
return InitError(strprintf(_("-maxmempool must be at least %d MB"), std::ceil(nMempoolSizeMin / 1000000.0)));
return InitError(strprintf(_("-maxmempool must be at least %d MB").translated, std::ceil(nMempoolSizeMin / 1000000.0)));
// incremental relay fee sets the minimum feerate increase necessary for BIP 125 replacement in the mempool
// and the amount the mempool min fee increases above the feerate of txs evicted due to mempool limiting.
if (gArgs.IsArgSet("-incrementalrelayfee"))
@ -1430,7 +1426,7 @@ bool AppInitParameterInteraction()
// block pruning; get the amount of disk space (in MiB) to allot for block & undo files
int64_t nPruneArg = gArgs.GetArg("-prune", 0);
if (nPruneArg < 0) {
return InitError(_("Prune cannot be configured with a negative value."));
return InitError(_("Prune cannot be configured with a negative value.").translated);
}
nPruneTarget = (uint64_t) nPruneArg * 1024 * 1024;
if (nPruneArg == 1) { // manual pruning: -prune=1
@ -1441,11 +1437,11 @@ bool AppInitParameterInteraction()
if (gArgs.GetBoolArg("-regtest", false)) {
// we use 1MB blocks to test this on regtest
if (nPruneTarget < 550 * 1024 * 1024) {
return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), 550));
return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number.").translated, 550));
}
} else {
if (nPruneTarget < MIN_DISK_SPACE_FOR_BLOCK_FILES) {
return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number."), MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024));
return InitError(strprintf(_("Prune configured below the minimum of %d MiB. Please use a higher number.").translated, MIN_DISK_SPACE_FOR_BLOCK_FILES / 1024 / 1024));
}
}
LogPrintf("Prune configured to target %u MiB on disk for block and undo files.\n", nPruneTarget / 1024 / 1024);
@ -1529,7 +1525,7 @@ bool AppInitParameterInteraction()
}
if (gArgs.IsArgSet("-masternode")) {
InitWarning(_("-masternode option is deprecated and ignored, specifying -masternodeblsprivkey is enough to start this node as a masternode."));
InitWarning(_("-masternode option is deprecated and ignored, specifying -masternodeblsprivkey is enough to start this node as a masternode.").translated);
}
if (gArgs.IsArgSet("-masternodeblsprivkey")) {
@ -1549,12 +1545,12 @@ bool AppInitParameterInteraction()
return InitError(strprintf("Masternode must be able to handle at least %d connections, set -maxconnections=%d", DEFAULT_MAX_PEER_CONNECTIONS, DEFAULT_MAX_PEER_CONNECTIONS));
}
if (gArgs.GetBoolArg("-disablegovernance", false)) {
return InitError(_("You can not disable governance validation on a masternode."));
return InitError(_("You can not disable governance validation on a masternode.").translated);
}
}
if (gArgs.IsArgSet("-litemode")) {
InitWarning(_("-litemode is deprecated.") + (gArgs.GetBoolArg("-litemode", false) ? (" " + _("Its replacement -disablegovernance has been forced instead.")) : ( " " + _("It has been replaced by -disablegovernance."))));
InitWarning(_("-litemode is deprecated.").translated + (gArgs.GetBoolArg("-litemode", false) ? (" " + _("Its replacement -disablegovernance has been forced instead.").translated) : ( " " + _("It has been replaced by -disablegovernance.").translated)));
gArgs.ForceRemoveArg("-litemode");
}
@ -1562,7 +1558,7 @@ bool AppInitParameterInteraction()
LogPrintf("fDisableGovernance %d\n", fDisableGovernance);
if (fDisableGovernance) {
InitWarning(_("You are starting with governance validation disabled.") + (fPruneMode ? " " + _("This is expected because you are running a pruned node.") : ""));
InitWarning(_("You are starting with governance validation disabled.").translated + (fPruneMode ? " " + _("This is expected because you are running a pruned node.").translated : ""));
}
return true;
@ -1573,10 +1569,10 @@ static bool LockDataDirectory(bool probeOnly)
// Make sure only a single Dash Core process is using the data directory.
fs::path datadir = GetDataDir();
if (!DirIsWritable(datadir)) {
return InitError(strprintf(_("Cannot write to data directory '%s'; check permissions."), datadir.string()));
return InitError(strprintf(_("Cannot write to data directory '%s'; check permissions.").translated, datadir.string()));
}
if (!LockDirectory(datadir, ".lock", probeOnly)) {
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running."), datadir.string(), PACKAGE_NAME));
return InitError(strprintf(_("Cannot obtain a lock on data directory %s. %s is probably already running.").translated, datadir.string(), PACKAGE_NAME));
}
return true;
}
@ -1594,7 +1590,7 @@ bool AppInitSanityChecks()
// Sanity check
if (!InitSanityCheck())
return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), PACKAGE_NAME));
return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down.").translated, PACKAGE_NAME));
// Probe the data directory lock to give an early error message, if possible
// We cannot hold the data directory lock here, as the forking for daemon() hasn't yet happened,
@ -1647,7 +1643,7 @@ bool AppInitMain(InitInterfaces& interfaces)
LogPrintf("Config file: %s\n", config_file_path.string());
} else if (gArgs.IsArgSet("-conf")) {
// Warn if no conf file exists at path provided by user
InitWarning(strprintf(_("The specified config file %s does not exist\n"), config_file_path.string()));
InitWarning(strprintf(_("The specified config file %s does not exist\n").translated, config_file_path.string()));
} else {
// Not categorizing as "Warning" because it's the default behavior
LogPrintf("Config file: %s (not found, skipping)\n", config_file_path.string());
@ -1694,19 +1690,19 @@ bool AppInitMain(InitInterfaces& interfaces)
}
for (const auto& address: vSporkAddresses) {
if (!sporkManager.SetSporkAddress(address)) {
return InitError(_("Invalid spork address specified with -sporkaddr"));
return InitError(_("Invalid spork address specified with -sporkaddr").translated);
}
}
int minsporkkeys = gArgs.GetArg("-minsporkkeys", Params().MinSporkKeys());
if (!sporkManager.SetMinSporkKeys(minsporkkeys)) {
return InitError(_("Invalid minimum number of spork signers specified with -minsporkkeys"));
return InitError(_("Invalid minimum number of spork signers specified with -minsporkkeys").translated);
}
if (gArgs.IsArgSet("-sporkkey")) { // spork priv key
if (!sporkManager.SetPrivKey(gArgs.GetArg("-sporkkey", ""))) {
return InitError(_("Unable to sign spork message, wrong key?"));
return InitError(_("Unable to sign spork message, wrong key?").translated);
}
}
@ -1746,7 +1742,7 @@ bool AppInitMain(InitInterfaces& interfaces)
{
uiInterface.InitMessage_connect(SetRPCWarmupStatus);
if (!AppInitServers())
return InitError(_("Unable to start HTTP server. See debug log for details."));
return InitError(_("Unable to start HTTP server. See debug log for details.").translated);
}
// ********************************************************* Step 5: verify wallet database integrity
@ -1782,12 +1778,12 @@ bool AppInitMain(InitInterfaces& interfaces)
for (const std::string& cmt : gArgs.GetArgs("-uacomment")) {
if (cmt != SanitizeString(cmt, SAFE_CHARS_UA_COMMENT))
return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters."), cmt));
return InitError(strprintf(_("User Agent comment (%s) contains unsafe characters.").translated, cmt));
uacomments.push_back(cmt);
}
strSubVersion = FormatSubVersion(CLIENT_NAME, CLIENT_VERSION, uacomments);
if (strSubVersion.size() > MAX_SUBVERSION_LENGTH) {
return InitError(strprintf(_("Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments."),
return InitError(strprintf(_("Total length of network version string (%i) exceeds maximum length (%i). Reduce the number or size of uacomments.").translated,
strSubVersion.size(), MAX_SUBVERSION_LENGTH));
}
@ -1796,7 +1792,7 @@ bool AppInitMain(InitInterfaces& interfaces)
for (const std::string& snet : gArgs.GetArgs("-onlynet")) {
enum Network net = ParseNetwork(snet);
if (net == NET_UNROUTABLE)
return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'"), snet));
return InitError(strprintf(_("Unknown network specified in -onlynet: '%s'").translated, snet));
nets.insert(net);
}
for (int n = 0; n < NET_MAX; n++) {
@ -1817,12 +1813,12 @@ bool AppInitMain(InitInterfaces& interfaces)
if (proxyArg != "" && proxyArg != "0") {
CService proxyAddr;
if (!Lookup(proxyArg.c_str(), proxyAddr, 9050, fNameLookup)) {
return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxyArg));
return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'").translated, proxyArg));
}
proxyType addrProxy = proxyType(proxyAddr, proxyRandomize);
if (!addrProxy.IsValid())
return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'"), proxyArg));
return InitError(strprintf(_("Invalid -proxy address or hostname: '%s'").translated, proxyArg));
SetProxy(NET_IPV4, addrProxy);
SetProxy(NET_IPV6, addrProxy);
@ -1841,11 +1837,11 @@ bool AppInitMain(InitInterfaces& interfaces)
} else {
CService onionProxy;
if (!Lookup(onionArg.c_str(), onionProxy, 9050, fNameLookup)) {
return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
return InitError(strprintf(_("Invalid -onion address or hostname: '%s'").translated, onionArg));
}
proxyType addrOnion = proxyType(onionProxy, proxyRandomize);
if (!addrOnion.IsValid())
return InitError(strprintf(_("Invalid -onion address or hostname: '%s'"), onionArg));
return InitError(strprintf(_("Invalid -onion address or hostname: '%s'").translated, onionArg));
SetProxy(NET_ONION, addrOnion);
SetReachable(NET_ONION, true);
}
@ -1874,12 +1870,12 @@ bool AppInitMain(InitInterfaces& interfaces)
asmap_path = GetDataDir() / asmap_path;
}
if (!fs::exists(asmap_path)) {
InitError(strprintf(_("Could not find asmap file %s"), asmap_path));
InitError(strprintf(_("Could not find asmap file %s").translated, asmap_path));
return false;
}
std::vector<bool> asmap = CAddrMan::DecodeAsmap(asmap_path);
if (asmap.size() == 0) {
InitError(strprintf(_("Could not parse asmap file %s"), asmap_path));
InitError(strprintf(_("Could not parse asmap file %s").translated, asmap_path));
return false;
}
const uint256 asmap_version = SerializeHash(asmap);
@ -1909,10 +1905,10 @@ bool AppInitMain(InitInterfaces& interfaces)
// ********************************************************* Step 7a: Load sporks
uiInterface.InitMessage(_("Loading sporks cache..."));
uiInterface.InitMessage(_("Loading sporks cache...").translated);
CFlatDB<CSporkManager> flatdb6("sporks.dat", "magicSporkCache");
if (!flatdb6.Load(sporkManager)) {
return InitError(_("Failed to load sporks cache from") + "\n" + (GetDataDir() / "sporks.dat").string());
return InitError(_("Failed to load sporks cache from").translated + "\n" + (GetDataDir() / "sporks.dat").string());
}
// ********************************************************* Step 7b: load block chain
@ -1959,7 +1955,7 @@ bool AppInitMain(InitInterfaces& interfaces)
bool fReset = fReindex;
std::string strLoadError;
uiInterface.InitMessage(_("Loading block index..."));
uiInterface.InitMessage(_("Loading block index...").translated);
do {
const int64_t load_block_index_start_time = GetTimeMillis();
@ -1998,47 +1994,47 @@ bool AppInitMain(InitInterfaces& interfaces)
// From here on out fReindex and fReset mean something different!
if (!LoadBlockIndex(chainparams)) {
if (ShutdownRequested()) break;
strLoadError = _("Error loading block database");
strLoadError = _("Error loading block database").translated;
break;
}
if (!fDisableGovernance && !gArgs.GetBoolArg("-txindex", DEFAULT_TXINDEX)
&& chainparams.NetworkIDString() != CBaseChainParams::REGTEST) { // TODO remove this when pruning is fixed. See https://github.com/dashpay/dash/pull/1817 and https://github.com/dashpay/dash/pull/1743
return InitError(_("Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index."));
return InitError(_("Transaction index can't be disabled with governance validation enabled. Either start with -disablegovernance command line switch or enable transaction index.").translated);
}
// If the loaded chain has a wrong genesis, bail out immediately
// (we're likely using a testnet datadir, or the other way around).
if (!::BlockIndex().empty() &&
!LookupBlockIndex(chainparams.GetConsensus().hashGenesisBlock)) {
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?"));
return InitError(_("Incorrect or no genesis block found. Wrong datadir for network?").translated);
}
if (!chainparams.GetConsensus().hashDevnetGenesisBlock.IsNull() && !::BlockIndex().empty() && ::BlockIndex().count(chainparams.GetConsensus().hashDevnetGenesisBlock) == 0)
return InitError(_("Incorrect or no devnet genesis block found. Wrong datadir for devnet specified?"));
return InitError(_("Incorrect or no devnet genesis block found. Wrong datadir for devnet specified?").translated);
// Check for changed -addressindex state
if (fAddressIndex != gArgs.GetBoolArg("-addressindex", DEFAULT_ADDRESSINDEX)) {
strLoadError = _("You need to rebuild the database using -reindex to change -addressindex");
strLoadError = _("You need to rebuild the database using -reindex to change -addressindex").translated;
break;
}
// Check for changed -timestampindex state
if (fTimestampIndex != gArgs.GetBoolArg("-timestampindex", DEFAULT_TIMESTAMPINDEX)) {
strLoadError = _("You need to rebuild the database using -reindex to change -timestampindex");
strLoadError = _("You need to rebuild the database using -reindex to change -timestampindex").translated;
break;
}
// Check for changed -spentindex state
if (fSpentIndex != gArgs.GetBoolArg("-spentindex", DEFAULT_SPENTINDEX)) {
strLoadError = _("You need to rebuild the database using -reindex to change -spentindex");
strLoadError = _("You need to rebuild the database using -reindex to change -spentindex").translated;
break;
}
// Check for changed -prune state. What we are concerned about is a user who has pruned blocks
// in the past, but is now trying to run unpruned.
if (fHavePruned && !fPruneMode) {
strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain");
strLoadError = _("You need to rebuild the database using -reindex to go back to unpruned mode. This will redownload the entire blockchain").translated;
break;
}
@ -2047,7 +2043,7 @@ bool AppInitMain(InitInterfaces& interfaces)
// (otherwise we use the one already on disk).
// This is called again in ThreadImport after the reindex completes.
if (!fReindex && !LoadGenesisBlock(chainparams)) {
strLoadError = _("Error initializing block database");
strLoadError = _("Error initializing block database").translated;
break;
}
@ -2061,20 +2057,20 @@ bool AppInitMain(InitInterfaces& interfaces)
::ChainstateActive().CoinsErrorCatcher().AddReadErrCallback([]() {
uiInterface.ThreadSafeMessageBox(
_("Error reading from database, shutting down."),
_("Error reading from database, shutting down.").translated,
"", CClientUIInterface::MSG_ERROR);
});
// If necessary, upgrade from older database format.
// This is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
if (!::ChainstateActive().CoinsDB().Upgrade()) {
strLoadError = _("Error upgrading chainstate database");
strLoadError = _("Error upgrading chainstate database").translated;
break;
}
// ReplayBlocks is a no-op if we cleared the coinsviewdb with -reindex or -reindex-chainstate
if (!::ChainstateActive().ReplayBlocks(chainparams)) {
strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.");
strLoadError = _("Unable to replay blocks. You will need to rebuild the database using -reindex-chainstate.").translated;
break;
}
@ -2084,7 +2080,7 @@ bool AppInitMain(InitInterfaces& interfaces)
// flush evodb
if (!evoDb->CommitRootTransaction()) {
strLoadError = _("Failed to commit EvoDB");
strLoadError = _("Failed to commit EvoDB").translated;
break;
}
@ -2093,7 +2089,7 @@ bool AppInitMain(InitInterfaces& interfaces)
if (!is_coinsview_empty) {
// LoadChainTip initializes the chain based on CoinsTip()'s best block
if (!::ChainstateActive().LoadChainTip(chainparams)) {
strLoadError = _("Error initializing block database");
strLoadError = _("Error initializing block database").translated;
break;
}
assert(::ChainActive().Tip() != NULL);
@ -2101,17 +2097,17 @@ bool AppInitMain(InitInterfaces& interfaces)
if (is_coinsview_empty && !evoDb->IsEmpty()) {
// EvoDB processed some blocks earlier but we have no blocks anymore, something is wrong
strLoadError = _("Error initializing block database");
strLoadError = _("Error initializing block database").translated;
break;
}
if (!deterministicMNManager->UpgradeDBIfNeeded() || !llmq::quorumBlockProcessor->UpgradeDB()) {
strLoadError = _("Error upgrading evo database");
strLoadError = _("Error upgrading evo database").translated;
break;
}
if (!is_coinsview_empty) {
uiInterface.InitMessage(_("Verifying blocks..."));
uiInterface.InitMessage(_("Verifying blocks...").translated);
if (fHavePruned && gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS) > MIN_BLOCKS_TO_KEEP) {
LogPrintf("Prune: pruned datadir may not have more than %d blocks; only checking available blocks\n",
MIN_BLOCKS_TO_KEEP);
@ -2122,13 +2118,13 @@ bool AppInitMain(InitInterfaces& interfaces)
if (tip && tip->nTime > GetAdjustedTime() + 2 * 60 * 60) {
strLoadError = _("The block database contains a block which appears to be from the future. "
"This may be due to your computer's date and time being set incorrectly. "
"Only rebuild the block database if you are sure that your computer's date and time are correct");
"Only rebuild the block database if you are sure that your computer's date and time are correct").translated;
break;
}
if (!CVerifyDB().VerifyDB(chainparams, &::ChainstateActive().CoinsDB(), gArgs.GetArg("-checklevel", DEFAULT_CHECKLEVEL),
gArgs.GetArg("-checkblocks", DEFAULT_CHECKBLOCKS))) {
strLoadError = _("Corrupted block database detected");
strLoadError = _("Corrupted block database detected").translated;
break;
}
@ -2138,7 +2134,7 @@ bool AppInitMain(InitInterfaces& interfaces)
}
} catch (const std::exception& e) {
LogPrintf("%s\n", e.what());
strLoadError = _("Error opening block database");
strLoadError = _("Error opening block database").translated;
break;
}
@ -2150,7 +2146,7 @@ bool AppInitMain(InitInterfaces& interfaces)
// first suggest a reindex
if (!fReset) {
bool fRet = uiInterface.ThreadSafeQuestion(
strLoadError + ".\n\n" + _("Do you want to rebuild the block database now?"),
strLoadError + ".\n\n" + _("Do you want to rebuild the block database now?").translated,
strLoadError + ".\nPlease restart with -reindex or -reindex-chainstate to recover.",
"", CClientUIInterface::MSG_ERROR | CClientUIInterface::BTN_ABORT);
if (fRet) {
@ -2215,7 +2211,7 @@ bool AppInitMain(InitInterfaces& interfaces)
LogPrintf("Unsetting NODE_NETWORK on prune mode\n");
nLocalServices = ServiceFlags(nLocalServices & ~NODE_NETWORK);
if (!fReindex) {
uiInterface.InitMessage(_("Pruning blockstore..."));
uiInterface.InitMessage(_("Pruning blockstore...").translated);
::ChainstateActive().PruneAndFlush();
}
}
@ -2235,7 +2231,7 @@ bool AppInitMain(InitInterfaces& interfaces)
auto binKey = ParseHex(strMasterNodeBLSPrivKey);
CBLSSecretKey keyOperator(binKey);
if (!keyOperator.IsValid()) {
return InitError(_("Invalid masternodeblsprivkey. Please see documentation."));
return InitError(_("Invalid masternodeblsprivkey. Please see documentation.").translated);
}
fMasternodeMode = true;
{
@ -2284,45 +2280,45 @@ bool AppInitMain(InitInterfaces& interfaces)
std::string strDBName;
strDBName = "mncache.dat";
uiInterface.InitMessage(_("Loading masternode cache..."));
uiInterface.InitMessage(_("Loading masternode cache...").translated);
CFlatDB<CMasternodeMetaMan> flatdb1(strDBName, "magicMasternodeCache");
if (fLoadCacheFiles) {
if(!flatdb1.Load(mmetaman)) {
return InitError(_("Failed to load masternode cache from") + "\n" + (pathDB / strDBName).string());
return InitError(_("Failed to load masternode cache from").translated + "\n" + (pathDB / strDBName).string());
}
} else {
CMasternodeMetaMan mmetamanTmp;
if(!flatdb1.Dump(mmetamanTmp)) {
return InitError(_("Failed to clear masternode cache at") + "\n" + (pathDB / strDBName).string());
return InitError(_("Failed to clear masternode cache at").translated + "\n" + (pathDB / strDBName).string());
}
}
strDBName = "governance.dat";
uiInterface.InitMessage(_("Loading governance cache..."));
uiInterface.InitMessage(_("Loading governance cache...").translated);
CFlatDB<CGovernanceManager> flatdb3(strDBName, "magicGovernanceCache");
if (fLoadCacheFiles && !fDisableGovernance) {
if(!flatdb3.Load(governance)) {
return InitError(_("Failed to load governance cache from") + "\n" + (pathDB / strDBName).string());
return InitError(_("Failed to load governance cache from").translated + "\n" + (pathDB / strDBName).string());
}
governance.InitOnLoad();
} else {
CGovernanceManager governanceTmp;
if(!flatdb3.Dump(governanceTmp)) {
return InitError(_("Failed to clear governance cache at") + "\n" + (pathDB / strDBName).string());
return InitError(_("Failed to clear governance cache at").translated + "\n" + (pathDB / strDBName).string());
}
}
strDBName = "netfulfilled.dat";
uiInterface.InitMessage(_("Loading fulfilled requests cache..."));
uiInterface.InitMessage(_("Loading fulfilled requests cache...").translated);
CFlatDB<CNetFulfilledRequestManager> flatdb4(strDBName, "magicFulfilledCache");
if (fLoadCacheFiles) {
if(!flatdb4.Load(netfulfilledman)) {
return InitError(_("Failed to load fulfilled requests cache from") + "\n" + (pathDB / strDBName).string());
return InitError(_("Failed to load fulfilled requests cache from").translated + "\n" + (pathDB / strDBName).string());
}
} else {
CNetFulfilledRequestManager netfulfilledmanTmp;
if(!flatdb4.Dump(netfulfilledmanTmp)) {
return InitError(_("Failed to clear fulfilled requests cache at") + "\n" + (pathDB / strDBName).string());
return InitError(_("Failed to clear fulfilled requests cache at").translated + "\n" + (pathDB / strDBName).string());
}
}
@ -2351,11 +2347,11 @@ bool AppInitMain(InitInterfaces& interfaces)
// ********************************************************* Step 11: import blocks
if (!CheckDiskSpace(GetDataDir())) {
InitError(strprintf(_("Error: Disk space is low for %s"), GetDataDir()));
InitError(strprintf(_("Error: Disk space is low for %s").translated, GetDataDir()));
return false;
}
if (!CheckDiskSpace(GetBlocksDir())) {
InitError(strprintf(_("Error: Disk space is low for %s"), GetBlocksDir()));
InitError(strprintf(_("Error: Disk space is low for %s").translated, GetBlocksDir()));
return false;
}
@ -2482,7 +2478,7 @@ bool AppInitMain(InitInterfaces& interfaces)
connOptions.socketEventsMode = CConnman::SOCKETEVENTS_KQUEUE;
#endif
} else {
return InitError(strprintf(_("Invalid -socketevents ('%s') specified. Only these modes are supported: %s"), strSocketEventsMode, GetSupportedSocketEventsStr()));
return InitError(strprintf(_("Invalid -socketevents ('%s') specified. Only these modes are supported: %s").translated, strSocketEventsMode, GetSupportedSocketEventsStr()));
}
if (!g_connman->Start(scheduler, connOptions)) {
@ -2492,7 +2488,7 @@ bool AppInitMain(InitInterfaces& interfaces)
// ********************************************************* Step 13: finished
SetRPCWarmupFinished();
uiInterface.InitMessage(_("Done loading"));
uiInterface.InitMessage(_("Done loading").translated);
for (const auto& client : interfaces.chain_clients) {
client->start(scheduler);

View File

@ -28,6 +28,7 @@
#include <primitives/block.h>
#include <rpc/server.h>
#include <shutdown.h>
#include <support/allocators/secure.h>
#include <sync.h>
#include <txmempool.h>
#include <ui_interface.h>
@ -48,7 +49,8 @@ class CWallet;
fs::path GetWalletDir();
std::vector<fs::path> ListWalletDir();
std::vector<std::shared_ptr<CWallet>> GetWallets();
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning);
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings);
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);
namespace interfaces {
@ -175,6 +177,7 @@ public:
MasternodeSyncImpl m_masternodeSync;
CoinJoinOptionsImpl m_coinjoin;
void initError(const std::string& message) override { InitError(message); }
bool parseParameters(int argc, const char* const argv[], std::string& error) override
{
return gArgs.ParseParameters(argc, argv, error);
@ -379,9 +382,9 @@ public:
}
return wallets;
}
std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::string& warning) override
std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
{
return MakeWallet(LoadWallet(*m_interfaces.chain, name, error, warning));
return MakeWallet(LoadWallet(*m_interfaces.chain, name, error, warnings));
}
EVO& evo() override { return m_evo; }
@ -390,6 +393,13 @@ public:
Masternode::Sync& masternodeSync() override { return m_masternodeSync; }
CoinJoin::Options& coinJoinOptions() override { return m_coinjoin; }
WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, std::unique_ptr<Wallet>& result) override
{
std::shared_ptr<CWallet> wallet;
WalletCreationStatus status = CreateWallet(*m_interfaces.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet);
result = MakeWallet(wallet);
return status;
}
std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) override
{
return MakeHandler(::uiInterface.InitMessage_connect(fn));

View File

@ -9,6 +9,7 @@
#include <net.h> // For CConnman::NumConnections
#include <net_types.h> // For banmap_t
#include <netaddress.h> // For Network
#include <support/allocators/secure.h> // For SecureString
#include <functional>
#include <memory>
@ -28,7 +29,9 @@ class Coin;
class RPCTimerInterface;
class UniValue;
class proxyType;
struct bilingual_str;
struct CNodeStateStats;
enum class WalletCreationStatus;
namespace interfaces {
class Handler;
@ -102,6 +105,9 @@ class Node
public:
virtual ~Node() {}
//! Send init error.
virtual void initError(const std::string& message) = 0;
//! Set command line arguments.
virtual bool parseParameters(int argc, const char* const argv[], std::string& error) = 0;
@ -262,7 +268,7 @@ public:
//! Attempts to load a wallet from file or directory.
//! The loaded wallet is also notified to handlers previously registered
//! with handleLoadWallet.
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, std::string& error, std::string& warning) = 0;
virtual std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) = 0;
//! Return interface for accessing evo related handler.
virtual EVO& evo() = 0;
@ -279,6 +285,9 @@ public:
//! Return interface for accessing coinjoin related handler.
virtual CoinJoin::Options& coinJoinOptions() = 0;
//! Create a wallet from file
virtual WalletCreationStatus createWallet(const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, std::unique_ptr<Wallet>& result) = 0;
//! Register handler for init messages.
using InitMessageFn = std::function<void(const std::string& message)>;
virtual std::unique_ptr<Handler> handleInitMessage(InitMessageFn fn) = 0;

View File

@ -173,9 +173,9 @@ public:
}
void abortRescan() override { m_wallet->AbortRescan(); }
bool backupWallet(const std::string& filename) override { return m_wallet->BackupWallet(filename); }
bool autoBackupWallet(const fs::path& wallet_path, std::string& strBackupWarningRet, std::string& strBackupErrorRet) override
bool autoBackupWallet(const fs::path& wallet_path, bilingual_str& error_string, std::vector<bilingual_str>& warnings) override
{
return m_wallet->AutoBackupWallet(wallet_path, strBackupWarningRet, strBackupErrorRet);
return m_wallet->AutoBackupWallet(wallet_path, error_string, warnings);
}
int64_t getKeysLeftSinceAutoBackup() override { return m_wallet->nKeysLeftSinceAutoBackup; }
std::string getWalletName() override { return m_wallet->GetName(); }
@ -276,7 +276,7 @@ public:
bool sign,
int& change_pos,
CAmount& fee,
std::string& fail_reason) override
bilingual_str& fail_reason) override
{
auto locked_chain = m_wallet->chain().lock();
LOCK(m_wallet->cs_wallet);

View File

@ -28,6 +28,7 @@ class CWallet;
enum isminetype : unsigned int;
enum class FeeReason;
typedef uint8_t isminefilter;
struct bilingual_str;
struct CRecipient;
namespace interfaces {
@ -95,7 +96,7 @@ public:
virtual bool backupWallet(const std::string& filename) = 0;
//! Automatically backup up wallet.
virtual bool autoBackupWallet(const fs::path& wallet_path, std::string& strBackupWarningRet, std::string& strBackupErrorRet) = 0;
virtual bool autoBackupWallet(const fs::path& wallet_path, bilingual_str& error_string, std::vector<bilingual_str>& warnings) = 0;
//! Get the number of keys since the last auto backup
virtual int64_t getKeysLeftSinceAutoBackup() = 0;
@ -164,7 +165,7 @@ public:
bool sign,
int& change_pos,
CAmount& fee,
std::string& fail_reason) = 0;
bilingual_str& fail_reason) = 0;
//! Commit transaction.
virtual void commitTransaction(CTransactionRef tx,

View File

@ -189,7 +189,7 @@ std::string SafeStringFormat(const std::string& fmt, const Args&... args)
return tinyformat::format(fmt, args...);
} catch (std::runtime_error& fmterr) {
std::string message = tinyformat::format("\n****TINYFORMAT ERROR****\n err=\"%s\"\n fmt=\"%s\"\n", fmterr.what(), fmt);
tfm::format(std::cerr, "%s", message.c_str());
tfm::format(std::cerr, "%s", message);
return message;
}
}

View File

@ -179,7 +179,7 @@ static bool ProcessUpnp()
if (externalIPAddress[0]) {
CNetAddr resolved;
if (LookupHost(externalIPAddress, resolved, false)) {
LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString().c_str());
LogPrintf("UPnP: ExternalIPAddress = %s\n", resolved.ToString());
AddLocal(resolved, LOCAL_MAPPED);
}
} else {

View File

@ -11,6 +11,7 @@
#include <shutdown.h>
#include <ui_interface.h>
#include <validation.h>
#include <util/translation.h>
class CMasternodeSync;
CMasternodeSync masternodeSync;
@ -87,9 +88,9 @@ void CMasternodeSync::SwitchToNextAsset(CConnman& connman)
std::string CMasternodeSync::GetSyncStatus() const
{
switch (nCurrentAsset) {
case MASTERNODE_SYNC_BLOCKCHAIN: return _("Synchronizing blockchain...");
case MASTERNODE_SYNC_GOVERNANCE: return _("Synchronizing governance objects...");
case MASTERNODE_SYNC_FINISHED: return _("Synchronization finished");
case MASTERNODE_SYNC_BLOCKCHAIN: return _("Synchronizing blockchain...").translated;
case MASTERNODE_SYNC_GOVERNANCE: return _("Synchronizing governance objects...").translated;
case MASTERNODE_SYNC_FINISHED: return _("Synchronization finished").translated;
default: return "";
}
}

View File

@ -21,6 +21,7 @@
#include <scheduler.h>
#include <ui_interface.h>
#include <util/strencodings.h>
#include <util/translation.h>
#include <validation.h>
#include <masternode/meta.h>
@ -2654,9 +2655,9 @@ bool CConnman::BindListenPort(const CService& addrBind, std::string& strError, N
{
int nErr = WSAGetLastError();
if (nErr == WSAEADDRINUSE)
strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running."), addrBind.ToString(), PACKAGE_NAME);
strError = strprintf(_("Unable to bind to %s on this computer. %s is probably already running.").translated, addrBind.ToString(), PACKAGE_NAME);
else
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)"), addrBind.ToString(), NetworkErrorString(nErr));
strError = strprintf(_("Unable to bind to %s on this computer (bind returned error %s)").translated, addrBind.ToString(), NetworkErrorString(nErr));
LogPrintf("%s\n", strError);
CloseSocket(hListenSocket);
return false;
@ -2666,7 +2667,7 @@ bool CConnman::BindListenPort(const CService& addrBind, std::string& strError, N
// Listen for incoming connections
if (listen(hListenSocket, SOMAXCONN) == SOCKET_ERROR)
{
strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)"), NetworkErrorString(WSAGetLastError()));
strError = strprintf(_("Error: Listening for incoming connections failed (listen returned error %s)").translated, NetworkErrorString(WSAGetLastError()));
LogPrintf("%s\n", strError);
CloseSocket(hListenSocket);
return false;
@ -2677,7 +2678,7 @@ bool CConnman::BindListenPort(const CService& addrBind, std::string& strError, N
struct kevent event;
EV_SET(&event, hListenSocket, EVFILT_READ, EV_ADD, 0, 0, nullptr);
if (kevent(kqueuefd, &event, 1, nullptr, 0, nullptr) != 0) {
strError = strprintf(_("Error: failed to add socket to kqueuefd (kevent returned error %s)"), NetworkErrorString(WSAGetLastError()));
strError = strprintf(_("Error: failed to add socket to kqueuefd (kevent returned error %s)").translated, NetworkErrorString(WSAGetLastError()));
LogPrintf("%s\n", strError);
CloseSocket(hListenSocket);
return false;
@ -2691,7 +2692,7 @@ bool CConnman::BindListenPort(const CService& addrBind, std::string& strError, N
event.data.fd = hListenSocket;
event.events = EPOLLIN;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, hListenSocket, &event) != 0) {
strError = strprintf(_("Error: failed to add socket to epollfd (epoll_ctl returned error %s)"), NetworkErrorString(WSAGetLastError()));
strError = strprintf(_("Error: failed to add socket to epollfd (epoll_ctl returned error %s)").translated, NetworkErrorString(WSAGetLastError()));
LogPrintf("%s\n", strError);
CloseSocket(hListenSocket);
return false;
@ -2861,7 +2862,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
if (fListen && !InitBinds(connOptions.vBinds, connOptions.vWhiteBinds)) {
if (clientInterface) {
clientInterface->ThreadSafeMessageBox(
_("Failed to listen on any port. Use -listen=0 if you want this."),
_("Failed to listen on any port. Use -listen=0 if you want this.").translated,
"", CClientUIInterface::MSG_ERROR);
}
return false;
@ -2872,7 +2873,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
}
if (clientInterface) {
clientInterface->InitMessage(_("Loading P2P addresses..."));
clientInterface->InitMessage(_("Loading P2P addresses...").translated);
}
// Load addresses from peers.dat
int64_t nStart = GetTimeMillis();
@ -2887,7 +2888,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
}
}
uiInterface.InitMessage(_("Starting network threads..."));
uiInterface.InitMessage(_("Starting network threads...").translated);
fAddressesInitialized = true;
@ -2968,7 +2969,7 @@ bool CConnman::Start(CScheduler& scheduler, const Options& connOptions)
if (connOptions.m_use_addrman_outgoing && !connOptions.m_specified_outgoing.empty()) {
if (clientInterface) {
clientInterface->ThreadSafeMessageBox(
_("Cannot provide specific connections and have addrman find outgoing connections at the same."),
_("Cannot provide specific connections and have addrman find outgoing connections at the same.").translated,
"", CClientUIInterface::MSG_ERROR);
}
return false;
@ -3640,7 +3641,7 @@ bool CConnman::NodeFullyConnected(const CNode* pnode)
void CConnman::PushMessage(CNode* pnode, CSerializedNetMsg&& msg)
{
size_t nMessageSize = msg.data.size();
LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.command.c_str()), nMessageSize, pnode->GetId());
LogPrint(BCLog::NET, "sending %s (%d bytes) peer=%d\n", SanitizeString(msg.command), nMessageSize, pnode->GetId());
// make sure we use the appropriate network transport format
std::vector<unsigned char> serializedHeader;

View File

@ -3,8 +3,10 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <net_permissions.h>
#include <util/system.h>
#include <netbase.h>
#include <util/error.h>
#include <util/system.h>
#include <util/translation.h>
// The parse the following format "perm1,perm2@xxxxxx"
bool TryParsePermissionFlags(const std::string str, NetPermissionFlags& output, size_t& readen, std::string& error)
@ -38,7 +40,7 @@ bool TryParsePermissionFlags(const std::string str, NetPermissionFlags& output,
else if (permission == "relay") NetPermissions::AddFlag(flags, PF_RELAY);
else if (permission.length() == 0); // Allow empty entries
else {
error = strprintf(_("Invalid P2P permission: '%s'"), permission);
error = strprintf(_("Invalid P2P permission: '%s'").translated, permission);
return false;
}
}
@ -70,11 +72,11 @@ bool NetWhitebindPermissions::TryParse(const std::string str, NetWhitebindPermis
const std::string strBind = str.substr(offset);
CService addrBind;
if (!Lookup(strBind.c_str(), addrBind, 0, false)) {
error = strprintf(_("Cannot resolve -%s address: '%s'"), "whitebind", strBind);
error = ResolveErrMsg("whitebind", strBind);
return false;
}
if (addrBind.GetPort() == 0) {
error = strprintf(_("Need to specify a port with -whitebind: '%s'"), strBind);
error = strprintf(_("Need to specify a port with -whitebind: '%s'").translated, strBind);
return false;
}
@ -94,7 +96,7 @@ bool NetWhitelistPermissions::TryParse(const std::string str, NetWhitelistPermis
CSubNet subnet;
LookupSubNet(net.c_str(), subnet);
if (!subnet.IsValid()) {
error = strprintf(_("Invalid netmask specified in -whitelist: '%s'"), net);
error = strprintf(_("Invalid netmask specified in -whitelist: '%s'").translated, net);
return false;
}

View File

@ -45,7 +45,7 @@ bool noui_ThreadSafeMessageBox(const std::string& message, const std::string& ca
if (!fSecure) {
LogPrintf("%s%s\n", strCaption, message);
}
tfm::format(std::cerr, "%s%s\n", strCaption.c_str(), message.c_str());
tfm::format(std::cerr, "%s%s\n", strCaption, message);
return false;
}
@ -99,4 +99,4 @@ void noui_reconnect()
noui_ThreadSafeQuestionConn.disconnect();
noui_InitMessageConn.disconnect();
noui_connect();
}
}

View File

@ -20,12 +20,13 @@
#include <QMessageBox>
#include <QPushButton>
AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent) :
AskPassphraseDialog::AskPassphraseDialog(Mode _mode, QWidget *parent, SecureString* passphrase_out) :
QDialog(parent),
ui(new Ui::AskPassphraseDialog),
mode(_mode),
model(nullptr),
fCapsLock(false)
fCapsLock(false),
m_passphrase_out(passphrase_out)
{
ui->setupUi(this);
@ -106,7 +107,7 @@ void AskPassphraseDialog::setModel(WalletModel *_model)
void AskPassphraseDialog::accept()
{
SecureString oldpass, newpass1, newpass2;
if(!model)
if (!model && mode != Encrypt)
return;
oldpass.reserve(MAX_PASSPHRASE_SIZE);
newpass1.reserve(MAX_PASSPHRASE_SIZE);
@ -135,38 +136,45 @@ void AskPassphraseDialog::accept()
{
if(newpass1 == newpass2)
{
if(model->setWalletEncrypted(true, newpass1))
{
if (model->wallet().hdEnabled()) {
QMessageBox::warning(this, tr("Wallet encrypted"),
QString encryption_reminder = tr("Remember that encrypting your wallet cannot fully protect "
"your funds from being stolen by malware infecting your computer.");
if (m_passphrase_out) {
m_passphrase_out->assign(newpass1);
QMessageBox::warning(this, tr("Wallet to be encrypted"),
"<qt>" +
tr("Your wallet is now encrypted. "
"Remember that encrypting your wallet cannot fully protect "
"your funds from being stolen by malware infecting your computer.") +
"<br><br><b>" +
tr("IMPORTANT: Any previous backups you have made of your wallet file "
"should be replaced with the newly generated, encrypted wallet file. "
"Previous backups of the unencrypted wallet file contain the same HD seed and "
"still have full access to all your funds just like the new, encrypted wallet.") +
"</b></qt>");
} else {
QMessageBox::warning(this, tr("Wallet encrypted"),
"<qt>" +
tr("Your wallet is now encrypted. "
"Remember that encrypting your wallet cannot fully protect "
"your funds from being stolen by malware infecting your computer.") +
"<br><br><b>" +
tr("IMPORTANT: Any previous backups you have made of your wallet file "
"should be replaced with the newly generated, encrypted wallet file. "
"For security reasons, previous backups of the unencrypted wallet file "
"will become useless as soon as you start using the new, encrypted wallet.") +
tr("Your wallet is about to be encrypted. ") + encryption_reminder +
"</b></qt>");
} else {
assert(model != nullptr);
if(model->setWalletEncrypted(true, newpass1))
{
if (model->wallet().hdEnabled()) {
QMessageBox::warning(this, tr("Wallet encrypted"),
"<qt>" +
tr("Your wallet is now encrypted. ") + encryption_reminder +
"<br><br><b>" +
tr("IMPORTANT: Any previous backups you have made of your wallet file "
"should be replaced with the newly generated, encrypted wallet file. "
"Previous backups of the unencrypted wallet file contain the same HD seed and "
"still have full access to all your funds just like the new, encrypted wallet.") +
"</b></qt>");
} else {
QMessageBox::warning(this, tr("Wallet encrypted"),
"<qt>" +
tr("Your wallet is now encrypted. ") + encryption_reminder +
"<br><br><b>" +
tr("IMPORTANT: Any previous backups you have made of your wallet file "
"should be replaced with the newly generated, encrypted wallet file. "
"For security reasons, previous backups of the unencrypted wallet file "
"will become useless as soon as you start using the new, encrypted wallet.") +
"</b></qt>");
}
}
else
{
QMessageBox::critical(this, tr("Wallet encryption failed"),
tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted."));
}
}
else
{
QMessageBox::critical(this, tr("Wallet encryption failed"),
tr("Wallet encryption failed due to an internal error. Your wallet was not encrypted."));
}
QDialog::accept(); // Success
}

View File

@ -7,6 +7,8 @@
#include <QDialog>
#include <support/allocators/secure.h>
class WalletModel;
namespace Ui {
@ -28,7 +30,7 @@ public:
Decrypt /**< Ask passphrase and decrypt wallet */
};
explicit AskPassphraseDialog(Mode mode, QWidget *parent);
explicit AskPassphraseDialog(Mode mode, QWidget *parent, SecureString* passphrase_out = nullptr);
~AskPassphraseDialog();
void accept() override;
@ -40,6 +42,7 @@ private:
Mode mode;
WalletModel *model;
bool fCapsLock;
SecureString* m_passphrase_out;
private Q_SLOTS:
void textChanged();

View File

@ -7,6 +7,7 @@
#include <qt/bitcoinunits.h>
#include <qt/clientmodel.h>
#include <qt/createwalletdialog.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/modaloverlay.h>
@ -38,9 +39,6 @@
#include <ui_interface.h>
#include <util/system.h>
#include <iostream>
#include <memory>
#include <QAction>
#include <QApplication>
#include <QButtonGroup>
@ -436,6 +434,9 @@ void BitcoinGUI::createActions()
m_close_wallet_action = new QAction(tr("Close Wallet..."), this);
m_close_wallet_action->setStatusTip(tr("Close wallet"));
m_create_wallet_action = new QAction(tr("Create Wallet..."), this);
m_create_wallet_action->setStatusTip(tr("Create a new wallet"));
showHelpMessageAction = new QAction(tr("&Command-line options"), this);
showHelpMessageAction->setMenuRole(QAction::NoRole);
showHelpMessageAction->setStatusTip(tr("Show the %1 help message to get a list with possible Dash command-line options").arg(PACKAGE_NAME));
@ -499,31 +500,11 @@ void BitcoinGUI::createActions()
continue;
}
connect(action, &QAction::triggered, [this, name, path] {
OpenWalletActivity* activity = m_wallet_controller->openWallet(path);
QProgressDialog* dialog = new QProgressDialog(this);
dialog->setLabelText(tr("Opening Wallet <b>%1</b>...").arg(name.toHtmlEscaped()));
dialog->setRange(0, 0);
dialog->setCancelButton(nullptr);
dialog->setWindowModality(Qt::ApplicationModal);
dialog->show();
connect(activity, &OpenWalletActivity::message, this, [this] (QMessageBox::Icon icon, QString text) {
QMessageBox box;
box.setIcon(icon);
box.setText(tr("Open Wallet Failed"));
box.setInformativeText(text);
box.setStandardButtons(QMessageBox::Ok);
box.setDefaultButton(QMessageBox::Ok);
connect(this, &QObject::destroyed, &box, &QDialog::accept);
box.exec();
});
connect(action, &QAction::triggered, [this, path] {
auto activity = new OpenWalletActivity(m_wallet_controller, this);
connect(activity, &OpenWalletActivity::opened, this, &BitcoinGUI::setCurrentWallet);
connect(activity, &OpenWalletActivity::finished, activity, &QObject::deleteLater);
connect(activity, &OpenWalletActivity::finished, dialog, &QObject::deleteLater);
bool invoked = QMetaObject::invokeMethod(activity, "open");
assert(invoked);
activity->open(path);
});
}
if (m_open_wallet_menu->isEmpty()) {
@ -534,6 +515,12 @@ void BitcoinGUI::createActions()
connect(m_close_wallet_action, &QAction::triggered, [this] {
m_wallet_controller->closeWallet(walletFrame->currentWalletModel(), this);
});
connect(m_create_wallet_action, &QAction::triggered, [this] {
auto activity = new CreateWalletActivity(m_wallet_controller, this);
connect(activity, &CreateWalletActivity::created, this, &BitcoinGUI::setCurrentWallet);
connect(activity, &CreateWalletActivity::finished, activity, &QObject::deleteLater);
activity->create();
});
}
#endif // ENABLE_WALLET
@ -558,6 +545,7 @@ void BitcoinGUI::createMenuBar()
QMenu *file = appMenuBar->addMenu(tr("&File"));
if(walletFrame)
{
file->addAction(m_create_wallet_action);
file->addAction(m_open_wallet_action);
file->addAction(m_close_wallet_action);
file->addSeparator();

View File

@ -160,6 +160,7 @@ private:
QAction* showBackupsAction = nullptr;
QAction* openAction = nullptr;
QAction* showHelpMessageAction = nullptr;
QAction* m_create_wallet_action{nullptr};
QAction* m_open_wallet_action{nullptr};
QMenu* m_open_wallet_menu{nullptr};
QAction* m_close_wallet_action{nullptr};

View File

@ -0,0 +1,61 @@
// Copyright (c) 2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#if defined(HAVE_CONFIG_H)
#include <config/dash-config.h>
#endif
#include <qt/createwalletdialog.h>
#include <qt/forms/ui_createwalletdialog.h>
#include <QPushButton>
CreateWalletDialog::CreateWalletDialog(QWidget* parent) :
QDialog(parent),
ui(new Ui::CreateWalletDialog)
{
ui->setupUi(this);
ui->buttonBox->button(QDialogButtonBox::Ok)->setText(tr("Create"));
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
ui->wallet_name_line_edit->setFocus(Qt::ActiveWindowFocusReason);
connect(ui->wallet_name_line_edit, &QLineEdit::textEdited, [this](const QString& text) {
ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!text.isEmpty());
});
connect(ui->encrypt_wallet_checkbox, &QCheckBox::toggled, [this](bool checked) {
// Disable disable_privkeys_checkbox when encrypt is set to true, enable it when encrypt is false
ui->disable_privkeys_checkbox->setEnabled(!checked);
// When the disable_privkeys_checkbox is disabled, uncheck it.
if (!ui->disable_privkeys_checkbox->isEnabled()) {
ui->disable_privkeys_checkbox->setChecked(false);
}
});
}
CreateWalletDialog::~CreateWalletDialog()
{
delete ui;
}
QString CreateWalletDialog::walletName() const
{
return ui->wallet_name_line_edit->text();
}
bool CreateWalletDialog::encrypt() const
{
return ui->encrypt_wallet_checkbox->isChecked();
}
bool CreateWalletDialog::disablePrivateKeys() const
{
return ui->disable_privkeys_checkbox->isChecked();
}
bool CreateWalletDialog::blank() const
{
return ui->blank_wallet_checkbox->isChecked();
}

View File

@ -0,0 +1,35 @@
// Copyright (c) 2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_QT_CREATEWALLETDIALOG_H
#define BITCOIN_QT_CREATEWALLETDIALOG_H
#include <QDialog>
class WalletModel;
namespace Ui {
class CreateWalletDialog;
}
/** Dialog for creating wallets
*/
class CreateWalletDialog : public QDialog
{
Q_OBJECT
public:
explicit CreateWalletDialog(QWidget* parent);
virtual ~CreateWalletDialog();
QString walletName() const;
bool encrypt() const;
bool disablePrivateKeys() const;
bool blank() const;
private:
Ui::CreateWalletDialog *ui;
};
#endif // BITCOIN_QT_CREATEWALLETDIALOG_H

View File

@ -11,8 +11,8 @@
#include <qt/bitcoingui.h>
#include <chainparams.h>
#include <qt/clientmodel.h>
#include <fs.h>
#include <qt/clientmodel.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/intro.h>
@ -36,11 +36,9 @@
#include <ui_interface.h>
#include <uint256.h>
#include <util/system.h>
#include <util/translation.h>
#include <memory>
#include <stdint.h>
#include <boost/thread.hpp>
#include <QApplication>
#include <QDebug>
@ -425,7 +423,7 @@ static void SetupUIArgs()
gArgs.AddArg("-splash", strprintf(QObject::tr("Show splash screen on startup (default: %u)").toStdString(), DEFAULT_SPLASHSCREEN), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
gArgs.AddArg("-uiplatform", strprintf("Select platform to customize UI for (one of windows, macosx, other; default: %s)", BitcoinGUI::DEFAULT_UIPLATFORM), ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::GUI);
gArgs.AddArg("-debug-ui", "Updates the UI's stylesheets in realtime with changes made to the css files in -custom-css-dir and forces some widgets to show up which are usually only visible under certain circumstances. (default: 0)", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::GUI);
gArgs.AddArg("-windowtitle=<name>", _("Sets a window title which is appended to \"Dash Core - \""), ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
gArgs.AddArg("-windowtitle=<name>", _("Sets a window title which is appended to \"Dash Core - \"").translated, ArgsManager::ALLOW_ANY, OptionsCategory::GUI);
}
int GuiMain(int argc, char* argv[])
@ -480,8 +478,11 @@ int GuiMain(int argc, char* argv[])
SetupUIArgs();
std::string error;
if (!node->parseParameters(argc, argv, error)) {
node->initError(strprintf("Error parsing command line arguments: %s\n", error));
// Create a message box, because the gui has neither been created nor has subscribed to core signals
QMessageBox::critical(nullptr, PACKAGE_NAME,
QObject::tr("Error parsing command line arguments: %1.").arg(QString::fromStdString(error)));
// message can not be translated because translations have not been initialized
QString::fromStdString("Error parsing command line arguments: %1.").arg(QString::fromStdString(error)));
return EXIT_FAILURE;
}
@ -524,11 +525,13 @@ int GuiMain(int argc, char* argv[])
/// - Do not call GetDataDir(true) before this step finishes
if (!fs::is_directory(GetDataDir(false)))
{
node->initError(strprintf("Specified data directory \"%s\" does not exist.\n", gArgs.GetArg("-datadir", "")));
QMessageBox::critical(nullptr, PACKAGE_NAME,
QObject::tr("Error: Specified data directory \"%1\" does not exist.").arg(QString::fromStdString(gArgs.GetArg("-datadir", ""))));
return EXIT_FAILURE;
}
if (!node->readConfigFiles(error)) {
node->initError(strprintf("Error reading configuration file: %s\n", error));
QMessageBox::critical(nullptr, PACKAGE_NAME,
QObject::tr("Error: Cannot parse configuration file: %1.").arg(QString::fromStdString(error)));
return EXIT_FAILURE;
@ -544,6 +547,7 @@ int GuiMain(int argc, char* argv[])
try {
node->selectParams(gArgs.GetChainName());
} catch(std::exception &e) {
node->initError(strprintf("%s\n", e.what()));
QMessageBox::critical(nullptr, PACKAGE_NAME, QObject::tr("Error: %1").arg(e.what()));
return EXIT_FAILURE;
}

View File

@ -11,7 +11,6 @@
#include <QApplication>
#include <memory>
#include <vector>
class BitcoinGUI;
class ClientModel;

View File

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>CreateWalletDialog</class>
<widget class="QDialog" name="CreateWalletDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>364</width>
<height>195</height>
</rect>
</property>
<property name="windowTitle">
<string>Create Wallet</string>
</property>
<widget class="QDialogButtonBox" name="buttonBox">
<property name="geometry">
<rect>
<x>10</x>
<y>140</y>
<width>341</width>
<height>40</height>
</rect>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
</property>
</widget>
<widget class="QLineEdit" name="wallet_name_line_edit">
<property name="geometry">
<rect>
<x>120</x>
<y>20</y>
<width>231</width>
<height>24</height>
</rect>
</property>
</widget>
<widget class="QLabel" name="label">
<property name="geometry">
<rect>
<x>20</x>
<y>20</y>
<width>101</width>
<height>21</height>
</rect>
</property>
<property name="text">
<string>Wallet Name</string>
</property>
</widget>
<widget class="QCheckBox" name="encrypt_wallet_checkbox">
<property name="geometry">
<rect>
<x>20</x>
<y>60</y>
<width>171</width>
<height>22</height>
</rect>
</property>
<property name="toolTip">
<string>Encrypt the wallet. The wallet will be encrypted with a password of your choice.</string>
</property>
<property name="text">
<string>Encrypt Wallet</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
<widget class="QCheckBox" name="disable_privkeys_checkbox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="geometry">
<rect>
<x>20</x>
<y>90</y>
<width>171</width>
<height>22</height>
</rect>
</property>
<property name="toolTip">
<string>Disable private keys for this wallet. Wallets with private keys disabled will have no private keys and cannot have an HD seed or imported private keys. This is ideal for watch-only wallets.</string>
</property>
<property name="text">
<string>Disable Private Keys</string>
</property>
</widget>
<widget class="QCheckBox" name="blank_wallet_checkbox">
<property name="geometry">
<rect>
<x>20</x>
<y>120</y>
<width>171</width>
<height>22</height>
</rect>
</property>
<property name="toolTip">
<string>Make a blank wallet. Blank wallets do not initially have private keys or scripts. Private keys and addresses can be imported, or an HD seed can be set, at a later time.</string>
</property>
<property name="text">
<string>Make Blank Wallet</string>
</property>
</widget>
</widget>
<tabstops>
<tabstop>wallet_name_line_edit</tabstop>
<tabstop>encrypt_wallet_checkbox</tabstop>
<tabstop>disable_privkeys_checkbox</tabstop>
<tabstop>blank_wallet_checkbox</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>buttonBox</sender>
<signal>accepted()</signal>
<receiver>CreateWalletDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>248</x>
<y>254</y>
</hint>
<hint type="destinationlabel">
<x>157</x>
<y>274</y>
</hint>
</hints>
</connection>
<connection>
<sender>buttonBox</sender>
<signal>rejected()</signal>
<receiver>CreateWalletDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>316</x>
<y>260</y>
</hint>
<hint type="destinationlabel">
<x>286</x>
<y>274</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -6,6 +6,8 @@
#ifndef BITCOIN_QT_GUICONSTANTS_H
#define BITCOIN_QT_GUICONSTANTS_H
#include <cstdint>
/* Milliseconds between model updates */
static const int MODEL_UPDATE_DELAY = 250;

View File

@ -4,6 +4,8 @@
#include <qt/dash.h>
#include <util/translation.h>
#include <QCoreApplication>
#include <functional>

View File

@ -19,6 +19,7 @@
#include <qt/networkstyle.h>
#include <ui_interface.h>
#include <util/system.h>
#include <util/translation.h>
#include <QApplication>
#include <QCloseEvent>
@ -171,8 +172,8 @@ static void InitMessage(SplashScreen *splash, const std::string &message)
static void ShowProgress(SplashScreen *splash, const std::string &title, int nProgress, bool resume_possible)
{
InitMessage(splash, title + std::string("\n") +
(resume_possible ? _("(press q to shutdown and continue later)")
: _("press q to shutdown")) +
(resume_possible ? _("(press q to shutdown and continue later)").translated
: _("press q to shutdown").translated) +
strprintf("\n%d", nProgress) + "%");
}
#ifdef ENABLE_WALLET

View File

@ -2,11 +2,18 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <qt/askpassphrasedialog.h>
#include <qt/createwalletdialog.h>
#include <qt/guiconstants.h>
#include <qt/guiutil.h>
#include <qt/walletcontroller.h>
#include <wallet/wallet.h>
#include <interfaces/handler.h>
#include <interfaces/node.h>
#include <util/string.h>
#include <util/translation.h>
#include <algorithm>
@ -14,10 +21,13 @@
#include <QMessageBox>
#include <QMutexLocker>
#include <QThread>
#include <QTimer>
#include <QWindow>
WalletController::WalletController(interfaces::Node& node, OptionsModel* options_model, QObject* parent)
: QObject(parent)
, m_activity_thread(new QThread(this))
, m_activity_worker(new QObject)
, m_node(node)
, m_options_model(options_model)
{
@ -29,15 +39,17 @@ WalletController::WalletController(interfaces::Node& node, OptionsModel* options
getOrCreateWallet(std::move(wallet));
}
m_activity_thread.start();
m_activity_worker->moveToThread(m_activity_thread);
m_activity_thread->start();
}
// Not using the default destructor because not all member types definitions are
// available in the header, just forward declared.
WalletController::~WalletController()
{
m_activity_thread.quit();
m_activity_thread.wait();
m_activity_thread->quit();
m_activity_thread->wait();
delete m_activity_worker;
}
std::vector<WalletModel*> WalletController::getOpenWallets() const
@ -60,13 +72,6 @@ std::map<std::string, bool> WalletController::listWalletDir() const
return wallets;
}
OpenWalletActivity* WalletController::openWallet(const std::string& name, QWidget* parent)
{
OpenWalletActivity* activity = new OpenWalletActivity(this, name);
activity->moveToThread(&m_activity_thread);
return activity;
}
void WalletController::closeWallet(WalletModel* wallet_model, QWidget* parent)
{
QMessageBox box(parent);
@ -146,23 +151,147 @@ void WalletController::removeAndDeleteWallet(WalletModel* wallet_model)
delete wallet_model;
}
OpenWalletActivity::OpenWalletActivity(WalletController* wallet_controller, const std::string& name)
: m_wallet_controller(wallet_controller)
, m_name(name)
{}
void OpenWalletActivity::open()
WalletControllerActivity::WalletControllerActivity(WalletController* wallet_controller, QWidget* parent_widget)
: QObject(wallet_controller)
, m_wallet_controller(wallet_controller)
, m_parent_widget(parent_widget)
{
std::string error, warning;
std::unique_ptr<interfaces::Wallet> wallet = m_wallet_controller->m_node.loadWallet(m_name, error, warning);
if (!warning.empty()) {
Q_EMIT message(QMessageBox::Warning, QString::fromStdString(warning));
}
WalletControllerActivity::~WalletControllerActivity()
{
delete m_progress_dialog;
}
void WalletControllerActivity::showProgressDialog(const QString& label_text)
{
m_progress_dialog = new QProgressDialog(m_parent_widget);
m_progress_dialog->setLabelText(label_text);
m_progress_dialog->setRange(0, 0);
m_progress_dialog->setCancelButton(nullptr);
m_progress_dialog->setWindowModality(Qt::ApplicationModal);
GUIUtil::PolishProgressDialog(m_progress_dialog);
}
CreateWalletActivity::CreateWalletActivity(WalletController* wallet_controller, QWidget* parent_widget)
: WalletControllerActivity(wallet_controller, parent_widget)
{
m_passphrase.reserve(MAX_PASSPHRASE_SIZE);
}
CreateWalletActivity::~CreateWalletActivity()
{
delete m_create_wallet_dialog;
delete m_passphrase_dialog;
}
void CreateWalletActivity::askPasshprase()
{
m_passphrase_dialog = new AskPassphraseDialog(AskPassphraseDialog::Encrypt, m_parent_widget, &m_passphrase);
m_passphrase_dialog->show();
connect(m_passphrase_dialog, &QObject::destroyed, [this] {
m_passphrase_dialog = nullptr;
});
connect(m_passphrase_dialog, &QDialog::accepted, [this] {
createWallet();
});
connect(m_passphrase_dialog, &QDialog::rejected, [this] {
Q_EMIT finished();
});
}
void CreateWalletActivity::createWallet()
{
showProgressDialog(tr("Creating Wallet <b>%1</b>...").arg(m_create_wallet_dialog->walletName().toHtmlEscaped()));
std::string name = m_create_wallet_dialog->walletName().toStdString();
uint64_t flags = 0;
if (m_create_wallet_dialog->disablePrivateKeys()) {
flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS;
}
if (wallet) {
Q_EMIT opened(m_wallet_controller->getOrCreateWallet(std::move(wallet)));
} else {
Q_EMIT message(QMessageBox::Critical, QString::fromStdString(error));
if (m_create_wallet_dialog->blank()) {
flags |= WALLET_FLAG_BLANK_WALLET;
}
QTimer::singleShot(500, worker(), [this, name, flags] {
std::unique_ptr<interfaces::Wallet> wallet;
WalletCreationStatus status = node().createWallet(m_passphrase, flags, name, m_error_message, m_warning_message, wallet);
if (status == WalletCreationStatus::SUCCESS) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet));
QTimer::singleShot(500, this, &CreateWalletActivity::finish);
});
}
void CreateWalletActivity::finish()
{
m_progress_dialog->hide();
if (!m_error_message.original.empty()) {
QMessageBox::critical(m_parent_widget, tr("Create wallet failed"), QString::fromStdString(m_error_message.translated));
} else if (!m_warning_message.empty()) {
QMessageBox::warning(m_parent_widget, tr("Create wallet warning"), QString::fromStdString(Join(m_warning_message, "\n", OpTranslated)));
}
if (m_wallet_model) Q_EMIT created(m_wallet_model);
Q_EMIT finished();
}
void CreateWalletActivity::create()
{
m_create_wallet_dialog = new CreateWalletDialog(m_parent_widget);
m_create_wallet_dialog->setWindowModality(Qt::ApplicationModal);
m_create_wallet_dialog->show();
connect(m_create_wallet_dialog, &QObject::destroyed, [this] {
m_create_wallet_dialog = nullptr;
});
connect(m_create_wallet_dialog, &QDialog::rejected, [this] {
Q_EMIT finished();
});
connect(m_create_wallet_dialog, &QDialog::accepted, [this] {
if (m_create_wallet_dialog->encrypt()) {
askPasshprase();
} else {
createWallet();
}
});
}
OpenWalletActivity::OpenWalletActivity(WalletController* wallet_controller, QWidget* parent_widget)
: WalletControllerActivity(wallet_controller, parent_widget)
{
}
void OpenWalletActivity::finish()
{
m_progress_dialog->hide();
if (!m_error_message.original.empty()) {
QMessageBox::critical(m_parent_widget, tr("Open wallet failed"), QString::fromStdString(m_error_message.translated));
} else if (!m_warning_message.empty()) {
QMessageBox::warning(m_parent_widget, tr("Open wallet warning"), QString::fromStdString(Join(m_warning_message, "\n", OpTranslated)));
}
if (m_wallet_model) Q_EMIT opened(m_wallet_model);
Q_EMIT finished();
}
void OpenWalletActivity::open(const std::string& path)
{
QString name = path.empty() ? QString("["+tr("default wallet")+"]") : QString::fromStdString(path);
showProgressDialog(tr("Opening Wallet <b>%1</b>...").arg(name.toHtmlEscaped()));
QTimer::singleShot(0, worker(), [this, path] {
std::unique_ptr<interfaces::Wallet> wallet = node().loadWallet(path, m_error_message, m_warning_message);
if (wallet) m_wallet_model = m_wallet_controller->getOrCreateWallet(std::move(wallet));
QTimer::singleShot(0, this, &OpenWalletActivity::finish);
});
}

View File

@ -6,15 +6,21 @@
#define BITCOIN_QT_WALLETCONTROLLER_H
#include <qt/walletmodel.h>
#include <support/allocators/secure.h>
#include <sync.h>
#include <util/translation.h>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <QMessageBox>
#include <QMutex>
#include <QProgressDialog>
#include <QThread>
#include <QTimer>
#include <QString>
class OptionsModel;
class PlatformStyle;
@ -24,7 +30,11 @@ class Handler;
class Node;
} // namespace interfaces
class AskPassphraseDialog;
class CreateWalletActivity;
class CreateWalletDialog;
class OpenWalletActivity;
class WalletControllerActivity;
/**
* Controller between interfaces::Node, WalletModel instances and the GUI.
@ -33,7 +43,6 @@ class WalletController : public QObject
{
Q_OBJECT
WalletModel* getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet);
void removeAndDeleteWallet(WalletModel* wallet_model);
public:
@ -43,11 +52,12 @@ public:
//! Returns wallet models currently open.
std::vector<WalletModel*> getOpenWallets() const;
WalletModel* getOrCreateWallet(std::unique_ptr<interfaces::Wallet> wallet);
//! Returns all wallet names in the wallet dir mapped to whether the wallet
//! is loaded.
std::map<std::string, bool> listWalletDir() const;
OpenWalletActivity* openWallet(const std::string& name, QWidget* parent = nullptr);
void closeWallet(WalletModel* wallet_model, QWidget* parent = nullptr);
Q_SIGNALS:
@ -57,34 +67,80 @@ Q_SIGNALS:
void coinsSent(WalletModel* wallet_model, SendCoinsRecipient recipient, QByteArray transaction);
private:
QThread m_activity_thread;
QThread* const m_activity_thread;
QObject* const m_activity_worker;
interfaces::Node& m_node;
OptionsModel* const m_options_model;
mutable QMutex m_mutex;
std::vector<WalletModel*> m_wallets;
std::unique_ptr<interfaces::Handler> m_handler_load_wallet;
friend class OpenWalletActivity;
friend class WalletControllerActivity;
};
class OpenWalletActivity : public QObject
class WalletControllerActivity : public QObject
{
Q_OBJECT
public:
OpenWalletActivity(WalletController* wallet_controller, const std::string& name);
public Q_SLOTS:
void open();
WalletControllerActivity(WalletController* wallet_controller, QWidget* parent_widget);
virtual ~WalletControllerActivity();
Q_SIGNALS:
void message(QMessageBox::Icon icon, const QString text);
void finished();
protected:
interfaces::Node& node() const { return m_wallet_controller->m_node; }
QObject* worker() const { return m_wallet_controller->m_activity_worker; }
void showProgressDialog(const QString& label_text);
WalletController* const m_wallet_controller;
QWidget* const m_parent_widget;
QProgressDialog* m_progress_dialog{nullptr};
WalletModel* m_wallet_model{nullptr};
bilingual_str m_error_message;
std::vector<bilingual_str> m_warning_message;
};
class CreateWalletActivity : public WalletControllerActivity
{
Q_OBJECT
public:
CreateWalletActivity(WalletController* wallet_controller, QWidget* parent_widget);
virtual ~CreateWalletActivity();
void create();
Q_SIGNALS:
void created(WalletModel* wallet_model);
private:
void askPasshprase();
void createWallet();
void finish();
SecureString m_passphrase;
CreateWalletDialog* m_create_wallet_dialog{nullptr};
AskPassphraseDialog* m_passphrase_dialog{nullptr};
};
class OpenWalletActivity : public WalletControllerActivity
{
Q_OBJECT
public:
OpenWalletActivity(WalletController* wallet_controller, QWidget* parent_widget);
void open(const std::string& path);
Q_SIGNALS:
void opened(WalletModel* wallet_model);
private:
WalletController* const m_wallet_controller;
std::string const m_name;
void finish();
};
#endif // BITCOIN_QT_WALLETCONTROLLER_H

View File

@ -21,6 +21,7 @@
#include <key_io.h>
#include <ui_interface.h>
#include <util/system.h> // for GetBoolArg
#include <util/translation.h>
#include <wallet/coincontrol.h>
#include <wallet/wallet.h>
@ -249,11 +250,11 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
}
CAmount nFeeRequired = 0;
std::string strFailReason;
bilingual_str error;
int nChangePosRet = -1;
auto& newTx = transaction.getWtx();
newTx = m_wallet->createTransaction(vecSend, coinControl, true /* sign */, nChangePosRet, nFeeRequired, strFailReason);
newTx = m_wallet->createTransaction(vecSend, coinControl, true /* sign */, nChangePosRet, nFeeRequired, error);
transaction.setTransactionFee(nFeeRequired);
if (fSubtractFeeFromAmount && newTx)
transaction.reassignAmounts();
@ -264,7 +265,7 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
{
return SendCoinsReturn(AmountWithFeeExceedsBalance);
}
Q_EMIT message(tr("Send Coins"), QString::fromStdString(strFailReason),
Q_EMIT message(tr("Send Coins"), QString::fromStdString(error.translated),
CClientUIInterface::MSG_ERROR);
return TransactionCreationFailed;
}
@ -429,11 +430,11 @@ bool WalletModel::changePassphrase(const SecureString &oldPass, const SecureStri
bool WalletModel::autoBackupWallet(QString& strBackupWarningRet, QString& strBackupErrorRet)
{
std::string strBackupWarning;
std::string strBackupError;
bool result = m_wallet->autoBackupWallet("", strBackupWarning, strBackupError);
strBackupWarningRet = QString::fromStdString(strBackupWarning);
strBackupErrorRet = QString::fromStdString(strBackupError);
bilingual_str strBackupError;
std::vector<bilingual_str> warnings;
bool result = m_wallet->autoBackupWallet("", strBackupError, warnings);
strBackupWarningRet = QString::fromStdString(Join(warnings, "\n", OpTranslated));
strBackupErrorRet = QString::fromStdString(strBackupError.translated);
return result;
}

View File

@ -64,7 +64,7 @@ static UniValue coinjoin(const JSONRPCRequest& request)
}
bool result = it->second->DoAutomaticDenominating(*g_connman);
return "Mixing " + (result ? "started successfully" : ("start failed: " + it->second->GetStatuses() + ", will retry"));
return "Mixing " + (result ? "started successfully" : ("start failed: " + it->second->GetStatuses().original + ", will retry"));
}
if (request.params[0].get_str() == "stop") {

View File

@ -1548,7 +1548,7 @@ UniValue joinpsbts(const JSONRPCRequest& request)
for (auto& psbt : psbtxs) {
for (unsigned int i = 0; i < psbt.tx->vin.size(); ++i) {
if (!merged_psbt.AddInput(psbt.tx->vin[i], psbt.inputs[i])) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input %s:%d exists in multiple PSBTs", psbt.tx->vin[i].prevout.hash.ToString().c_str(), psbt.tx->vin[i].prevout.n));
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Input %s:%d exists in multiple PSBTs", psbt.tx->vin[i].prevout.hash.ToString(), psbt.tx->vin[i].prevout.n));
}
}
for (unsigned int i = 0; i < psbt.tx->vout.size(); ++i) {

View File

@ -20,6 +20,7 @@
#include <rpc/util.h>
#include <util/moneystr.h>
#include <util/validation.h>
#include <util/translation.h>
#include <validation.h>
#ifdef ENABLE_WALLET
@ -229,10 +230,10 @@ static void FundSpecialTx(CWallet* pwallet, CMutableTransaction& tx, const Speci
CTransactionRef newTx;
CAmount nFee;
int nChangePos = -1;
std::string strFailReason;
bilingual_str strFailReason;
if (!pwallet->CreateTransaction(*locked_chain, vecSend, newTx, nFee, nChangePos, strFailReason, coinControl, false, tx.vExtraPayload.size())) {
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason);
throw JSONRPCError(RPC_INTERNAL_ERROR, strFailReason.original);
}
tx.vin = newTx->vin;

View File

@ -590,7 +590,7 @@ enum class ParseScriptContext {
}
uint32_t p;
if (!ParseUInt32(std::string(elem.begin(), elem.end()), &p)) {
error = strprintf("Key path value '%s' is not a valid uint32", std::string(elem.begin(), elem.end()).c_str());
error = strprintf("Key path value '%s' is not a valid uint32", std::string(elem.begin(), elem.end()));
return false;
} else if (p > 0x7FFFFFFFUL) {
error = strprintf("Key path value %u is out of range", p);
@ -727,7 +727,7 @@ std::unique_ptr<DescriptorImpl> ParseScript(Span<const char>& sp, ParseScriptCon
uint32_t thres;
std::vector<std::unique_ptr<PubkeyProvider>> providers;
if (!ParseUInt32(std::string(threshold.begin(), threshold.end()), &thres)) {
error = strprintf("Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()).c_str());
error = strprintf("Multi threshold '%s' is not valid", std::string(threshold.begin(), threshold.end()));
return nullptr;
}
size_t script_size = 0;

View File

@ -526,7 +526,7 @@ static void PrintCrashInfo(const crash_info& ci)
{
auto str = GetCrashInfoStr(ci);
LogPrintf("%s", str); /* Continued */
tfm::format(std::cerr, "%s", str.c_str());
tfm::format(std::cerr, "%s", str);
fflush(stderr);
}

View File

@ -113,7 +113,7 @@ static void potential_deadlock_detected(const LockPair& mismatch, const LockStac
if (i.first == mismatch.second) {
strOutput += " (2)";
}
strOutput += strprintf(" %s\n", i.second.ToString().c_str());
strOutput += strprintf(" %s\n", i.second.ToString());
}
std::string mutex_a, mutex_b;
@ -127,13 +127,13 @@ static void potential_deadlock_detected(const LockPair& mismatch, const LockStac
strOutput += " (2)";
mutex_b = i.second.Name();
}
strOutput += strprintf(" %s\n", i.second.ToString().c_str());
strOutput += strprintf(" %s\n", i.second.ToString());
}
LogPrintf("%s\n", strOutput.c_str());
LogPrintf("%s\n", strOutput);
if (g_debug_lockorder_abort) {
tfm::format(std::cerr, "Assertion failed: detected inconsistent lock order for %s, details in debug log.\n", s2.back().second.ToString().c_str());
tfm::format(std::cerr, "Assertion failed: detected inconsistent lock order for %s, details in debug log.\n", s2.back().second.ToString());
abort();
}
throw std::logic_error(strprintf("potential deadlock detected: %s -> %s -> %s", mutex_b, mutex_a, mutex_b));
@ -236,7 +236,7 @@ template <typename MutexType>
void AssertLockHeldInternal(const char* pszName, const char* pszFile, int nLine, MutexType* cs)
{
if (LockHeld(cs)) return;
tfm::format(std::cerr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
tfm::format(std::cerr, "Assertion failed: lock %s not held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld());
abort();
}
template void AssertLockHeldInternal(const char*, const char*, int, Mutex*);
@ -245,7 +245,7 @@ template void AssertLockHeldInternal(const char*, const char*, int, CCriticalSec
void AssertLockNotHeldInternal(const char* pszName, const char* pszFile, int nLine, void* cs)
{
if (!LockHeld(cs)) return;
tfm::format(std::cerr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld().c_str());
tfm::format(std::cerr, "Assertion failed: lock %s held in %s:%i; locks held:\n%s", pszName, pszFile, nLine, LocksHeld());
abort();
}

View File

@ -24,6 +24,7 @@
#include <util/memory.h>
#include <util/strencodings.h>
#include <util/time.h>
#include <util/translation.h>
#include <validation.h>
#include <validationinterface.h>

View File

@ -12,6 +12,7 @@
#include <sync.h>
#include <ui_interface.h>
#include <util/system.h>
#include <util/translation.h>
#include <warnings.h>
@ -100,7 +101,7 @@ void AddTimeData(const CNetAddr& ip, int64_t nOffsetSample)
if (!fMatch)
{
fDone = true;
std::string strMessage = strprintf(_("Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly."), PACKAGE_NAME);
std::string strMessage = strprintf(_("Please check that your computer's date and time are correct! If your clock is wrong, %s will not work properly.").translated, PACKAGE_NAME);
SetMiscWarning(strMessage);
uiInterface.ThreadSafeMessageBox(strMessage, "", CClientUIInterface::MSG_WARNING);
}

View File

@ -5,12 +5,13 @@
#include <txdb.h>
#include <random.h>
#include <pow.h>
#include <random.h>
#include <shutdown.h>
#include <uint256.h>
#include <util/system.h>
#include <ui_interface.h>
#include <util/translation.h>
#include <util/vector.h>
#include <stdint.h>
@ -478,7 +479,7 @@ bool CCoinsViewDB::Upgrade() {
int64_t count = 0;
LogPrintf("Upgrading utxo-set database...\n");
LogPrintf("[0%%]..."); /* Continued */
uiInterface.ShowProgress(_("Upgrading UTXO database"), 0, true);
uiInterface.ShowProgress(_("Upgrading UTXO database").translated, 0, true);
size_t batch_size = 1 << 24;
CDBBatch batch(db);
int reportDone = 0;
@ -493,7 +494,7 @@ bool CCoinsViewDB::Upgrade() {
if (count++ % 256 == 0) {
uint32_t high = 0x100 * *key.second.begin() + *(key.second.begin() + 1);
int percentageDone = (int)(high * 100.0 / 65536.0 + 0.5);
uiInterface.ShowProgress(_("Upgrading UTXO database"), percentageDone, true);
uiInterface.ShowProgress(_("Upgrading UTXO database").translated, percentageDone, true);
if (reportDone < percentageDone/10) {
// report max. every 10% step
LogPrintf("[%d%%]...", percentageDone); /* Continued */

View File

@ -4,7 +4,9 @@
#include <util/error.h>
#include <tinyformat.h>
#include <util/system.h>
#include <util/translation.h>
std::string TransactionErrorString(const TransactionError err)
{
@ -34,12 +36,17 @@ std::string TransactionErrorString(const TransactionError err)
assert(false);
}
std::string AmountHighWarn(const std::string& optname)
std::string ResolveErrMsg(const std::string& optname, const std::string& strBind)
{
return strprintf(_("%s is set very high!"), optname);
return strprintf(_("Cannot resolve -%s address: '%s'").translated, optname, strBind);
}
std::string AmountErrMsg(const char* const optname, const std::string& strValue)
std::string AmountHighWarn(const std::string& optname)
{
return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue);
return strprintf(_("%s is set very high!").translated, optname);
}
std::string AmountErrMsg(const std::string& optname, const std::string& strValue)
{
return strprintf(_("Invalid amount for -%s=<amount>: '%s'").translated, optname, strValue);
}

View File

@ -10,7 +10,7 @@
* string functions. Types and functions defined here should not require any
* outside dependencies.
*
* Error types defined here can be used in different parts of the bitcoin
* Error types defined here can be used in different parts of the
* codebase, to avoid the need to write boilerplate code catching and
* translating errors passed across wallet/node/rpc/gui code boundaries.
*/
@ -32,7 +32,10 @@ enum class TransactionError {
std::string TransactionErrorString(const TransactionError error);
std::string ResolveErrMsg(const std::string& optname, const std::string& strBind);
std::string AmountHighWarn(const std::string& optname);
std::string AmountErrMsg(const char* const optname, const std::string& strValue);
std::string AmountErrMsg(const std::string& optname, const std::string& strValue);
#endif // BITCOIN_UTIL_ERROR_H

View File

@ -13,6 +13,7 @@
#include <util/getuniquepath.h>
#include <util/strencodings.h>
#include <util/string.h>
#include <util/translation.h>
#if (defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__))
@ -325,7 +326,7 @@ public:
LogPrintf("Warning: parsed potentially confusing double-negative %s=%s\n", key, val);
val = "1";
} else {
error = strprintf("Negating of %s is meaningless and therefore forbidden", key.c_str());
error = strprintf("Negating of %s is meaningless and therefore forbidden", key);
return false;
}
}
@ -437,7 +438,7 @@ bool ArgsManager::ParseParameters(int argc, const char* const argv[], std::strin
}
m_command_line_args[key].push_back(val);
} else {
error = strprintf("Invalid parameter %s", key.c_str());
error = strprintf("Invalid parameter %s", key);
return false;
}
}
@ -734,7 +735,7 @@ void PrintExceptionContinue(const std::exception_ptr pex, const char* pszExcepti
{
std::string message = strprintf("\"%s\" raised an exception\n%s", pszExceptionOrigin, GetPrettyExceptionStr(pex));
LogPrintf("\n\n************************\n%s\n", message);
tfm::format(std::cerr, "\n\n************************\n%s\n", message.c_str());
tfm::format(std::cerr, "\n\n************************\n%s\n", message);
}
fs::path GetDefaultDataDir()
@ -907,7 +908,7 @@ bool ArgsManager::ReadConfigStream(std::istream& stream, const std::string& file
if (ignore_invalid_keys) {
LogPrintf("Ignoring unknown configuration value %s\n", option.first);
} else {
error = strprintf("Invalid configuration value %s", option.first.c_str());
error = strprintf("Invalid configuration value %s", option.first);
return false;
}
}
@ -961,7 +962,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
if (!ReadConfigStream(include_config, to_include, error, ignore_invalid_keys)) {
return false;
}
LogPrintf("Included configuration file %s\n", to_include.c_str());
LogPrintf("Included configuration file %s\n", to_include);
} else {
error = "Failed to include configuration file " + to_include;
return false;
@ -981,7 +982,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
}
}
for (const std::string& to_include : includeconf) {
tfm::format(std::cerr, "warning: -includeconf cannot be used from included files; ignoring -includeconf=%s\n", to_include.c_str());
tfm::format(std::cerr, "warning: -includeconf cannot be used from included files; ignoring -includeconf=%s\n", to_include);
}
}
} else {
@ -995,7 +996,7 @@ bool ArgsManager::ReadConfigFiles(std::string& error, bool ignore_invalid_keys)
// If datadir is changed in .conf file:
ClearDatadirCache();
if (!fs::is_directory(GetDataDir(false))) {
error = strprintf("specified data directory \"%s\" does not exist.", gArgs.GetArg("-datadir", "").c_str());
error = strprintf("specified data directory \"%s\" does not exist.", gArgs.GetArg("-datadir", ""));
return false;
}
return true;
@ -1210,7 +1211,7 @@ void RenameThreadPool(ctpl::thread_pool& tp, const char* baseName)
for (int i = 0; i < tp.size(); i++) {
futures[i] = tp.push([baseName, i, cond, mutex, &doneCnt](int threadId) {
util::ThreadRename(strprintf("%s-%d", baseName, i).c_str());
util::ThreadRename(strprintf("%s-%d", baseName, i));
std::unique_lock<std::mutex> l(*mutex);
doneCnt++;
cond->wait(l);
@ -1295,8 +1296,8 @@ int GetNumCores()
std::string CopyrightHolders(const std::string& strPrefix, unsigned int nStartYear, unsigned int nEndYear)
{
// std::string strCopyrightHolders = strPrefix + strprintf(" %u-%u ", nStartYear, nEndYear) + strprintf(_(COPYRIGHT_HOLDERS), _(COPYRIGHT_HOLDERS_SUBSTITUTION));
const auto copyright_devs = strprintf(_(COPYRIGHT_HOLDERS), COPYRIGHT_HOLDERS_SUBSTITUTION);
// std::string strCopyrightHolders = strPrefix + strprintf(" %u-%u ", nStartYear, nEndYear) + strprintf(_(COPYRIGHT_HOLDERS).translated, _(COPYRIGHT_HOLDERS_SUBSTITUTION));
const auto copyright_devs = strprintf(_(COPYRIGHT_HOLDERS).translated, COPYRIGHT_HOLDERS_SUBSTITUTION);
std::string strCopyrightHolders = strPrefix + strprintf(" %u-%u ", nStartYear, nEndYear) + copyright_devs;
// Check for untranslated substitution to make sure Dash Core copyright is not removed by accident

View File

@ -60,18 +60,6 @@ int64_t GetStartupTime();
extern const char * const BITCOIN_CONF_FILENAME;
/** Translate a message to the native language of the user. */
const extern std::function<std::string(const char*)> G_TRANSLATION_FUN;
/**
* Translation function.
* If no translation function is set, simply return the input.
*/
inline std::string _(const char* psz)
{
return G_TRANSLATION_FUN ? (G_TRANSLATION_FUN)(psz) : psz;
}
void SetupEnvironment();
bool SetupNetworking();

56
src/util/translation.h Normal file
View File

@ -0,0 +1,56 @@
// Copyright (c) 2019 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_UTIL_TRANSLATION_H
#define BITCOIN_UTIL_TRANSLATION_H
#include <tinyformat.h>
#include <utility>
/**
* Bilingual messages:
* - in GUI: user's native language + untranslated (i.e. English)
* - in log and stderr: untranslated only
*/
struct bilingual_str {
std::string original;
std::string translated;
};
inline bilingual_str operator+(const bilingual_str& lhs, const bilingual_str& rhs)
{
return bilingual_str{
lhs.original + rhs.original,
lhs.translated + rhs.translated};
}
/** Mark a bilingual_str as untranslated */
inline static bilingual_str Untranslated(std::string original) { return {original, original}; }
/** Unary operator to return the original */
inline static std::string OpOriginal(const bilingual_str& b) { return b.original; }
/** Unary operator to return the translation */
inline static std::string OpTranslated(const bilingual_str& b) { return b.translated; }
namespace tinyformat {
template <typename... Args>
bilingual_str format(const bilingual_str& fmt, const Args&... args)
{
return bilingual_str{format(fmt.original, args...), format(fmt.translated, args...)};
}
} // namespace tinyformat
/** Translate a message to the native language of the user. */
const extern std::function<std::string(const char*)> G_TRANSLATION_FUN;
/**
* Translation function.
* If no translation function is set, simply return the input.
*/
inline bilingual_str _(const char* psz)
{
return bilingual_str{psz, G_TRANSLATION_FUN ? (G_TRANSLATION_FUN)(psz) : psz};
}
#endif // BITCOIN_UTIL_TRANSLATION_H

View File

@ -38,6 +38,7 @@
#include <uint256.h>
#include <undo.h>
#include <util/strencodings.h>
#include <util/translation.h>
#include <util/validation.h>
#include <util/system.h>
#include <validationinterface.h>
@ -1580,7 +1581,7 @@ static bool AbortNode(const std::string& strMessage, const std::string& userMess
if (!userMessage.empty()) {
uiInterface.ThreadSafeMessageBox(userMessage, "", CClientUIInterface::MSG_ERROR | prefix);
} else {
uiInterface.ThreadSafeMessageBox(_("Error: A fatal internal error occurred, see debug.log for details"), "", CClientUIInterface::MSG_ERROR | CClientUIInterface::MSG_NOPREFIX);
uiInterface.ThreadSafeMessageBox(_("Error: A fatal internal error occurred, see debug.log for details").translated, "", CClientUIInterface::MSG_ERROR | CClientUIInterface::MSG_NOPREFIX);
}
StartShutdown();
return false;
@ -2512,7 +2513,7 @@ bool CChainState::FlushStateToDisk(
if (fDoFullFlush || fPeriodicWrite) {
// Depend on nMinDiskSpace to ensure we can write block index
if (!CheckDiskSpace(GetBlocksDir())) {
return AbortNode(state, "Disk space is too low!", _("Error: Disk space is too low!"), CClientUIInterface::MSG_NOPREFIX);
return AbortNode(state, "Disk space is too low!", _("Error: Disk space is too low!").translated, CClientUIInterface::MSG_NOPREFIX);
}
// First make sure all block and undo data is flushed to disk.
{
@ -2561,7 +2562,7 @@ bool CChainState::FlushStateToDisk(
// an overestimation, as most will delete an existing entry or
// overwrite one. Still, use a conservative safety factor of 2.
if (!CheckDiskSpace(GetDataDir(), 48 * 2 * 2 * CoinsTip().GetCacheSize())) {
return AbortNode(state, "Disk space is too low!", _("Error: Disk space is too low!"), CClientUIInterface::MSG_NOPREFIX);
return AbortNode(state, "Disk space is too low!", _("Error: Disk space is too low!").translated, CClientUIInterface::MSG_NOPREFIX);
}
// Flush the chainstate (which may refer to block index entries).
if (!CoinsTip().Flush())
@ -2640,7 +2641,7 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
WarningBitsConditionChecker checker(bit);
ThresholdState state = checker.GetStateFor(pindex, chainParams.GetConsensus(), warningcache[bit]);
if (state == ThresholdState::ACTIVE || state == ThresholdState::LOCKED_IN) {
const std::string strWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)"), bit);
const std::string strWarning = strprintf(_("Warning: unknown new rules activated (versionbit %i)").translated, bit);
if (state == ThresholdState::ACTIVE) {
DoWarning(strWarning);
} else {
@ -2657,7 +2658,7 @@ void static UpdateTip(const CBlockIndex *pindexNew, const CChainParams& chainPar
pindex = pindex->pprev;
}
if (nUpgraded > 0)
AppendWarning(warningMessages, strprintf(_("%d of last 100 blocks have unexpected version"), nUpgraded));
AppendWarning(warningMessages, strprintf(_("%d of last 100 blocks have unexpected version").translated, nUpgraded));
}
LogPrintf("%s: new best=%s height=%d version=0x%08x log2_work=%.8g tx=%lu date='%s' progress=%f cache=%.1fMiB(%utxo) evodb_cache=%.1fMiB%s\n", __func__,
pindexNew->GetBlockHash().ToString(), pindexNew->nHeight, pindexNew->nVersion,
@ -3669,7 +3670,7 @@ static bool FindBlockPos(FlatFilePos &pos, unsigned int nAddSize, unsigned int n
bool out_of_space;
size_t bytes_allocated = BlockFileSeq().Allocate(pos, nAddSize, out_of_space);
if (out_of_space) {
return AbortNode("Disk space is too low!", _("Error: Disk space is too low!"), CClientUIInterface::MSG_NOPREFIX);
return AbortNode("Disk space is too low!", _("Error: Disk space is too low!").translated, CClientUIInterface::MSG_NOPREFIX);
}
if (bytes_allocated != 0 && fPruneMode) {
fCheckForPruning = true;
@ -3693,7 +3694,7 @@ static bool FindUndoPos(CValidationState &state, int nFile, FlatFilePos &pos, un
bool out_of_space;
size_t bytes_allocated = UndoFileSeq().Allocate(pos, nAddSize, out_of_space);
if (out_of_space) {
return AbortNode(state, "Disk space is too low!", _("Error: Disk space is too low!"), CClientUIInterface::MSG_NOPREFIX);
return AbortNode(state, "Disk space is too low!", _("Error: Disk space is too low!").translated, CClientUIInterface::MSG_NOPREFIX);
}
if (bytes_allocated != 0 && fPruneMode) {
fCheckForPruning = true;
@ -4615,7 +4616,7 @@ bool CChainState::LoadChainTip(const CChainParams& chainparams)
CVerifyDB::CVerifyDB()
{
uiInterface.ShowProgress(_("Verifying blocks..."), 0, false);
uiInterface.ShowProgress(_("Verifying blocks...").translated, 0, false);
}
CVerifyDB::~CVerifyDB()
@ -4652,7 +4653,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
LogPrintf("[%d%%]...", percentageDone); /* Continued */
reportDone = percentageDone/10;
}
uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone, false);
uiInterface.ShowProgress(_("Verifying blocks...").translated, percentageDone, false);
if (pindex->nHeight <= ::ChainActive().Height()-nCheckDepth)
break;
if (fPruneMode && !(pindex->nStatus & BLOCK_HAVE_DATA)) {
@ -4710,7 +4711,7 @@ bool CVerifyDB::VerifyDB(const CChainParams& chainparams, CCoinsView *coinsview,
LogPrintf("[%d%%]...", percentageDone); /* Continued */
reportDone = percentageDone/10;
}
uiInterface.ShowProgress(_("Verifying blocks..."), percentageDone, false);
uiInterface.ShowProgress(_("Verifying blocks...").translated, percentageDone, false);
pindex = ::ChainActive().Next(pindex);
CBlock block;
if (!ReadBlockFromDisk(block, pindex, chainparams.GetConsensus()))
@ -4766,7 +4767,7 @@ bool CChainState::ReplayBlocks(const CChainParams& params)
if (hashHeads.empty()) return true; // We're already in a consistent state.
if (hashHeads.size() != 2) return error("ReplayBlocks(): unknown inconsistent state");
uiInterface.ShowProgress(_("Replaying blocks..."), 0, false);
uiInterface.ShowProgress(_("Replaying blocks...").translated, 0, false);
LogPrintf("Replaying blocks\n");
const CBlockIndex* pindexOld = nullptr; // Old tip during the interrupted flush.
@ -4817,7 +4818,7 @@ bool CChainState::ReplayBlocks(const CChainParams& params)
for (int nHeight = nForkHeight + 1; nHeight <= pindexNew->nHeight; ++nHeight) {
const CBlockIndex* pindex = pindexNew->GetAncestor(nHeight);
LogPrintf("Rolling forward %s (%i)\n", pindex->GetBlockHash().ToString(), nHeight);
uiInterface.ShowProgress(_("Replaying blocks..."), (int) ((nHeight - nForkHeight) * 100.0 / (pindexNew->nHeight - nForkHeight)) , false);
uiInterface.ShowProgress(_("Replaying blocks...").translated, (int) ((nHeight - nForkHeight) * 100.0 / (pindexNew->nHeight - nForkHeight)) , false);
if (!RollforwardBlock(pindex, cache, params)) return false;
}

View File

@ -7,6 +7,7 @@
#include <wallet/db.h>
#include <util/strencodings.h>
#include <util/translation.h>
#include <stdint.h>
@ -291,7 +292,7 @@ BerkeleyBatch::SafeDbt::operator Dbt*()
return &m_dbt;
}
bool BerkeleyDatabase::Verify(std::string& errorStr)
bool BerkeleyDatabase::Verify(bilingual_str& errorStr)
{
fs::path walletDir = env->Directory();
fs::path file_path = walletDir / strFile;

View File

@ -20,6 +20,8 @@
#include <unordered_map>
#include <vector>
struct bilingual_str;
#if defined(__GNUC__) && !defined(__clang__)
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-override"
@ -145,7 +147,7 @@ public:
void ReloadDbEnv() override;
/** Verifies the environment and database file */
bool Verify(std::string& error) override;
bool Verify(bilingual_str& error) override;
/**
* Pointer to shared database environment.

View File

@ -15,6 +15,8 @@
#include <memory>
#include <string>
struct bilingual_str;
/** Given a wallet directory path or legacy file path, return path to main data file in the wallet database. */
fs::path WalletDataFilePath(const fs::path& wallet_path);
void SplitWalletPath(const fs::path& wallet_path, fs::path& env_directory, std::string& database_filename);
@ -145,7 +147,7 @@ public:
int64_t nLastWalletUpdate;
/** Verifies the environment and database file */
virtual bool Verify(std::string& error) = 0;
virtual bool Verify(bilingual_str& error) = 0;
std::string m_file_path;
@ -189,7 +191,7 @@ public:
bool PeriodicFlush() override { return true; }
void IncrementUpdateCounter() override { ++nUpdateCounter; }
void ReloadDbEnv() override {}
bool Verify(std::string& errorStr) override { return true; }
bool Verify(bilingual_str& errorStr) override { return true; }
std::unique_ptr<DatabaseBatch> MakeBatch(const char* mode = "r+", bool flush_on_close = true) override { return MakeUnique<DummyBatch>(); }
};

View File

@ -10,6 +10,7 @@
#include <util/error.h>
#include <util/system.h>
#include <util/moneystr.h>
#include <util/translation.h>
#include <validation.h>
#include <walletinitinterface.h>
#include <wallet/wallet.h>
@ -101,7 +102,7 @@ bool WalletInit::ParameterInteraction() const
return true;
} else if (gArgs.IsArgSet("-masternodeblsprivkey")) {
return InitError(_("You can not start a masternode with wallet enabled."));
return InitError(_("You can not start a masternode with wallet enabled.").translated);
}
const bool is_multiwallet = gArgs.GetArgs("-wallet").size() > 1;
@ -129,7 +130,7 @@ bool WalletInit::ParameterInteraction() const
int rescan_mode = gArgs.GetArg("-rescan", 0);
if (rescan_mode < 0 || rescan_mode > 2) {
LogPrintf("%s: Warning: incorrect -rescan mode, falling back to default value.\n", __func__);
InitWarning(_("Incorrect -rescan mode, falling back to default value"));
InitWarning(_("Incorrect -rescan mode, falling back to default value").translated);
gArgs.ForceRemoveArg("-rescan");
}
@ -142,17 +143,17 @@ bool WalletInit::ParameterInteraction() const
if (gArgs.GetBoolArg("-sysperms", false))
return InitError("-sysperms is not allowed in combination with enabled wallet functionality");
if (gArgs.GetArg("-prune", 0) && gArgs.GetBoolArg("-rescan", false))
return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again."));
return InitError(_("Rescans are not possible in pruned mode. You will need to use -reindex which will download the whole blockchain again.").translated);
if (gArgs.IsArgSet("-walletbackupsdir")) {
if (!fs::is_directory(gArgs.GetArg("-walletbackupsdir", ""))) {
InitWarning(strprintf(_("Warning: incorrect parameter %s, path must exist! Using default path."), "-walletbackupsdir"));
InitWarning(strprintf(_("Warning: incorrect parameter %s, path must exist! Using default path.").translated, "-walletbackupsdir"));
gArgs.ForceRemoveArg("-walletbackupsdir");
}
}
if (gArgs.IsArgSet("-hdseed") && IsHex(gArgs.GetArg("-hdseed", "not hex")) && (gArgs.IsArgSet("-mnemonic") || gArgs.IsArgSet("-mnemonicpassphrase"))) {
InitWarning(strprintf(_("Warning: can't use %s and %s together, will prefer %s"), "-hdseed", "-mnemonic/-mnemonicpassphrase", "-hdseed"));
InitWarning(strprintf(_("Warning: can't use %s and %s together, will prefer %s").translated, "-hdseed", "-mnemonic/-mnemonicpassphrase", "-hdseed"));
gArgs.ForceRemoveArg("-mnemonic");
gArgs.ForceRemoveArg("-mnemonicpassphrase");
}
@ -160,7 +161,7 @@ bool WalletInit::ParameterInteraction() const
// begin PrivateSend -> CoinJoin migration
if (gArgs.IsArgSet("-privatesendrounds")) {
int nRoundsDeprecated = gArgs.GetArg("-privatesendrounds", DEFAULT_COINJOIN_ROUNDS);
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesendrounds", "-coinjoinrounds"));
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesendrounds", "-coinjoinrounds"));
if (gArgs.SoftSetArg("-coinjoinrounds", itostr(nRoundsDeprecated))) {
LogPrintf("%s: parameter interaction: -privatesendrounds=%d -> setting -coinjoinrounds=%d\n", __func__, nRoundsDeprecated, nRoundsDeprecated);
}
@ -168,7 +169,7 @@ bool WalletInit::ParameterInteraction() const
}
if (gArgs.IsArgSet("-privatesendamount")) {
int nAmountDeprecated = gArgs.GetArg("-privatesendamount", DEFAULT_COINJOIN_AMOUNT);
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesendamount", "-coinjoinamount"));
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesendamount", "-coinjoinamount"));
if (gArgs.SoftSetArg("-coinjoinamount", itostr(nAmountDeprecated))) {
LogPrintf("%s: parameter interaction: -privatesendamount=%d -> setting -coinjoinamount=%d\n", __func__, nAmountDeprecated, nAmountDeprecated);
}
@ -176,7 +177,7 @@ bool WalletInit::ParameterInteraction() const
}
if (gArgs.IsArgSet("-privatesenddenomsgoal")) {
int nDenomsGoalDeprecated = gArgs.GetArg("-privatesenddenomsgoal", DEFAULT_COINJOIN_DENOMS_GOAL);
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesenddenomsgoal", "-coinjoindenomsgoal"));
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesenddenomsgoal", "-coinjoindenomsgoal"));
if (gArgs.SoftSetArg("-coinjoindenomsgoal", itostr(nDenomsGoalDeprecated))) {
LogPrintf("%s: parameter interaction: -privatesenddenomsgoal=%d -> setting -coinjoindenomsgoal=%d\n", __func__, nDenomsGoalDeprecated, nDenomsGoalDeprecated);
}
@ -184,7 +185,7 @@ bool WalletInit::ParameterInteraction() const
}
if (gArgs.IsArgSet("-privatesenddenomshardcap")) {
int nDenomsHardcapDeprecated = gArgs.GetArg("-privatesenddenomshardcap", DEFAULT_COINJOIN_DENOMS_HARDCAP);
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesenddenomshardcap", "-coinjoindenomshardcap"));
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesenddenomshardcap", "-coinjoindenomshardcap"));
if (gArgs.SoftSetArg("-coinjoindenomshardcap", itostr(nDenomsHardcapDeprecated))) {
LogPrintf("%s: parameter interaction: -privatesenddenomshardcap=%d -> setting -coinjoindenomshardcap=%d\n", __func__, nDenomsHardcapDeprecated, nDenomsHardcapDeprecated);
}
@ -192,7 +193,7 @@ bool WalletInit::ParameterInteraction() const
}
if (gArgs.IsArgSet("-privatesendsessions")) {
int nSessionsDeprecated = gArgs.GetArg("-privatesendsessions", DEFAULT_COINJOIN_SESSIONS);
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesendsessions", "-coinjoinsessions"));
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesendsessions", "-coinjoinsessions"));
if (gArgs.SoftSetArg("-coinjoinsessions", itostr(nSessionsDeprecated))) {
LogPrintf("%s: parameter interaction: -privatesendsessions=%d -> setting -coinjoinsessions=%d\n", __func__, nSessionsDeprecated, nSessionsDeprecated);
}
@ -200,7 +201,7 @@ bool WalletInit::ParameterInteraction() const
}
if (gArgs.IsArgSet("-enableprivatesend")) {
bool fEnablePSDeprecated = gArgs.GetBoolArg("-enableprivatesend", 0);
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-enableprivatesend", "-enablecoinjoin"));
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-enableprivatesend", "-enablecoinjoin"));
if (gArgs.SoftSetBoolArg("-enablecoinjoin", fEnablePSDeprecated)) {
LogPrintf("%s: parameter interaction: -enableprivatesend=%d -> setting -enablecoinjoin=%d\n", __func__, fEnablePSDeprecated, fEnablePSDeprecated);
}
@ -208,7 +209,7 @@ bool WalletInit::ParameterInteraction() const
}
if (gArgs.IsArgSet("-privatesendautostart")) {
bool fAutoStartDeprecated = gArgs.GetBoolArg("-privatesendautostart", DEFAULT_COINJOIN_AUTOSTART);
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesendautostart", "-coinjoinautostart"));
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesendautostart", "-coinjoinautostart"));
if (gArgs.SoftSetBoolArg("-coinjoinautostart", fAutoStartDeprecated)) {
LogPrintf("%s: parameter interaction: -privatesendautostart=%d -> setting -coinjoinautostart=%d\n", __func__, fAutoStartDeprecated, fAutoStartDeprecated);
}
@ -216,7 +217,7 @@ bool WalletInit::ParameterInteraction() const
}
if (gArgs.IsArgSet("-privatesendmultisession")) {
bool fMultiSessionDeprecated = gArgs.GetBoolArg("-privatesendmultisession", DEFAULT_COINJOIN_MULTISESSION);
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead"), "-privatesendmultisession", "-coinjoinmultisession"));
InitWarning(strprintf(_("Warning: %s is deprecated, please use %s instead").translated, "-privatesendmultisession", "-coinjoinmultisession"));
if (gArgs.SoftSetBoolArg("-coinjoinmultisession", fMultiSessionDeprecated)) {
LogPrintf("%s: parameter interaction: -privatesendmultisession=%d -> setting -coinjoinmultisession=%d\n", __func__, fMultiSessionDeprecated, fMultiSessionDeprecated);
}
@ -225,7 +226,7 @@ bool WalletInit::ParameterInteraction() const
// end PrivateSend -> CoinJoin migration
if (gArgs.GetArg("-coinjoindenomshardcap", DEFAULT_COINJOIN_DENOMS_HARDCAP) < gArgs.GetArg("-coinjoindenomsgoal", DEFAULT_COINJOIN_DENOMS_GOAL)) {
return InitError(strprintf(_("%s can't be lower than %s"), "-coinjoindenomshardcap", "-coinjoindenomsgoal"));
return InitError(strprintf(_("%s can't be lower than %s").translated, "-coinjoindenomshardcap", "-coinjoindenomsgoal"));
}
return true;

View File

@ -10,7 +10,9 @@
#include <coinjoin/options.h>
#include <interfaces/chain.h>
#include <scheduler.h>
#include <util/string.h>
#include <util/system.h>
#include <util/translation.h>
#include <wallet/wallet.h>
bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
@ -21,14 +23,14 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wal
// The canonical path cleans the path, preventing >1 Berkeley environment instances for the same directory
fs::path canonical_wallet_dir = fs::canonical(wallet_dir, error);
if (error || !fs::exists(wallet_dir)) {
chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist"), wallet_dir.string()));
chain.initError(strprintf(_("Specified -walletdir \"%s\" does not exist").translated, wallet_dir.string()));
return false;
} else if (!fs::is_directory(wallet_dir)) {
chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory"), wallet_dir.string()));
chain.initError(strprintf(_("Specified -walletdir \"%s\" is not a directory").translated, wallet_dir.string()));
return false;
// The canonical path transforms relative paths into absolute ones, so we check the non-canonical version
} else if (!wallet_dir.is_absolute()) {
chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path"), wallet_dir.string()));
chain.initError(strprintf(_("Specified -walletdir \"%s\" is a relative path").translated, wallet_dir.string()));
return false;
}
gArgs.ForceSetArg("-walletdir", canonical_wallet_dir.string());
@ -36,7 +38,7 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wal
LogPrintf("Using wallet directory %s\n", GetWalletDir().string());
chain.initMessage(_("Verifying wallet(s)..."));
chain.initMessage(_("Verifying wallet(s)...").translated);
// Keep track of each wallet absolute path to detect duplicates.
std::set<fs::path> wallet_paths;
@ -45,16 +47,18 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wal
WalletLocation location(wallet_file);
if (!wallet_paths.insert(location.GetPath()).second) {
chain.initError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified."), wallet_file));
chain.initError(strprintf(_("Error loading wallet %s. Duplicate -wallet filename specified.").translated, wallet_file));
return false;
}
std::string error_string;
std::string warning_string;
bool verify_success = CWallet::Verify(chain, location, error_string, warning_string);
if (!error_string.empty()) chain.initError(error_string);
if (!warning_string.empty()) chain.initWarning(warning_string);
if (!verify_success) return false;
bilingual_str error_string;
std::vector<bilingual_str> warnings;
bool verify_success = CWallet::Verify(chain, location, error_string, warnings);
if (!warnings.empty()) chain.initWarning(Join(warnings, "\n", OpTranslated));
if (!verify_success) {
chain.initError(error_string.translated);
return false;
}
}
return true;
@ -63,8 +67,12 @@ bool VerifyWallets(interfaces::Chain& chain, const std::vector<std::string>& wal
bool LoadWallets(interfaces::Chain& chain, const std::vector<std::string>& wallet_files)
{
for (const std::string& walletFile : wallet_files) {
std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile));
bilingual_str error_string;
std::vector<bilingual_str> warnings;
std::shared_ptr<CWallet> pwallet = CWallet::CreateWalletFromFile(chain, WalletLocation(walletFile), error_string, warnings);
if (!warnings.empty()) chain.initWarning(Join(warnings, "\n", OpTranslated));
if (!pwallet) {
chain.initError(error_string.translated);
return false;
}
}

View File

@ -17,6 +17,7 @@
#include <util/bip32.h>
#include <util/system.h>
#include <util/time.h>
#include <util/translation.h>
#include <validation.h>
#include <wallet/wallet.h>
@ -565,7 +566,7 @@ UniValue importwallet(const JSONRPCRequest& request)
// Use uiInterface.ShowProgress instead of pwallet.ShowProgress because pwallet.ShowProgress has a cancel button tied to AbortRescan which
// we don't want for this progress bar showing the import progress. uiInterface.ShowProgress does not have a cancel button.
pwallet->chain().showProgress(strprintf("%s " + _("Importing..."), pwallet->GetDisplayName()), 0, false); // show progress dialog in GUI
pwallet->chain().showProgress(strprintf("%s " + _("Importing...").translated, pwallet->GetDisplayName()), 0, false); // show progress dialog in GUI
std::vector<std::tuple<CKey, int64_t, bool, std::string>> keys;
std::vector<std::pair<CScript, int64_t>> scripts;
while (file.good()) {
@ -728,7 +729,7 @@ UniValue importelectrumwallet(const JSONRPCRequest& request)
int64_t nFilesize = std::max((int64_t)1, (int64_t)file.tellg());
file.seekg(0, file.beg);
pwallet->ShowProgress(_("Importing..."), 0); // show progress dialog in GUI
pwallet->ShowProgress(_("Importing...").translated, 0); // show progress dialog in GUI
if(strFileExt == "csv") {
while (file.good()) {
@ -1071,7 +1072,7 @@ UniValue dumpwallet(const JSONRPCRequest& request)
file << "# End of dump\n";
file.close();
std::string strWarning = strprintf(_("%s file contains all private keys from this wallet. Do not share it with anyone!"), request.params[0].get_str().c_str());
std::string strWarning = strprintf(_("%s file contains all private keys from this wallet. Do not share it with anyone!").translated, request.params[0].get_str());
obj.pushKV("keys", int(vKeyBirth.size()));
obj.pushKV("filename", filepath.string());
obj.pushKV("warning", strWarning);

View File

@ -21,6 +21,8 @@
#include <util/fees.h>
#include <util/system.h>
#include <util/moneystr.h>
#include <util/string.h>
#include <util/translation.h>
#include <util/url.h>
#include <util/validation.h>
#include <util/vector.h>
@ -297,16 +299,16 @@ static CTransactionRef SendMoney(interfaces::Chain::Lock& locked_chain, CWallet
// Create and send the transaction
CAmount nFeeRequired = 0;
std::string strError;
bilingual_str error;
std::vector<CRecipient> vecSend;
int nChangePosRet = -1;
CRecipient recipient = {scriptPubKey, nValue, fSubtractFeeFromAmount};
vecSend.push_back(recipient);
CTransactionRef tx;
if (!pwallet->CreateTransaction(locked_chain, vecSend, tx, nFeeRequired, nChangePosRet, strError, coin_control)) {
if (!pwallet->CreateTransaction(locked_chain, vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control)) {
if (!fSubtractFeeFromAmount && nValue + nFeeRequired > curBalance)
strError = strprintf("Error: This transaction requires a transaction fee of at least %s", FormatMoney(nFeeRequired));
throw JSONRPCError(RPC_WALLET_ERROR, strError);
error = strprintf(Untranslated("Error: This transaction requires a transaction fee of at least %s"), FormatMoney(nFeeRequired));
throw JSONRPCError(RPC_WALLET_ERROR, error.original);
}
pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */);
return tx;
@ -946,11 +948,11 @@ static UniValue sendmany(const JSONRPCRequest& request)
// Send
CAmount nFeeRequired = 0;
int nChangePosRet = -1;
std::string strFailReason;
bilingual_str error;
CTransactionRef tx;
bool fCreated = pwallet->CreateTransaction(*locked_chain, vecSend, tx, nFeeRequired, nChangePosRet, strFailReason, coin_control);
bool fCreated = pwallet->CreateTransaction(*locked_chain, vecSend, tx, nFeeRequired, nChangePosRet, error, coin_control);
if (!fCreated)
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, strFailReason);
throw JSONRPCError(RPC_WALLET_INSUFFICIENT_FUNDS, error.original);
pwallet->CommitTransaction(tx, std::move(mapValue), {} /* orderForm */);
return tx->GetHash().GetHex();
}
@ -2724,13 +2726,14 @@ static UniValue loadwallet(const JSONRPCRequest& request)
}
}
std::string error, warning;
std::shared_ptr<CWallet> const wallet = LoadWallet(*g_rpc_interfaces->chain, location, error, warning);
if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error);
bilingual_str error;
std::vector<bilingual_str> warnings;
std::shared_ptr<CWallet> const wallet = LoadWallet(*g_rpc_interfaces->chain, location, error, warnings);
if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error.original);
UniValue obj(UniValue::VOBJ);
obj.pushKV("name", wallet->GetName());
obj.pushKV("warning", warning);
obj.pushKV("warning", Join(warnings, "\n", OpOriginal));
return obj;
}
@ -2762,81 +2765,42 @@ static UniValue createwallet(const JSONRPCRequest& request)
if (request.fHelp || !help.IsValidNumArgs(request.params.size())) {
throw std::runtime_error(help.ToString());
}
std::string error;
std::string warning;
uint64_t flags = 0;
if (!request.params[1].isNull() && request.params[1].get_bool()) {
flags |= WALLET_FLAG_DISABLE_PRIVATE_KEYS;
}
bool create_blank = false; // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
if (!request.params[2].isNull() && request.params[2].get_bool()) {
create_blank = true;
flags |= WALLET_FLAG_BLANK_WALLET;
}
SecureString passphrase;
passphrase.reserve(100);
std::vector<bilingual_str> warnings;
if (!request.params[3].isNull()) {
passphrase = request.params[3].get_str().c_str();
if (passphrase.empty()) {
// Empty string is invalid
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Cannot encrypt a wallet with a blank password");
}
// Born encrypted wallets need to be blank first so that wallet creation doesn't make any unencrypted keys
flags |= WALLET_FLAG_BLANK_WALLET;
}
WalletLocation location(request.params[0].get_str());
if (location.Exists()) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet " + location.GetName() + " already exists.");
}
// Wallet::Verify will check if we're trying to create a wallet with a duplication name.
if (!CWallet::Verify(*g_rpc_interfaces->chain, location, error, warning)) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet file verification failed: " + error);
}
const auto wallet = CWallet::CreateWalletFromFile(*g_rpc_interfaces->chain, location, flags);
if (!wallet) {
throw JSONRPCError(RPC_WALLET_ERROR, "Wallet creation failed.");
}
// Encrypt the wallet if there's a passphrase
if (!passphrase.empty() && !(flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
if (!wallet->EncryptWallet(passphrase)) {
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Wallet created but failed to encrypt.");
}
if (!create_blank) {
// Unlock the wallet
if (!wallet->Unlock(passphrase)) {
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, "Error: Wallet was encrypted but could not be unlocked");
}
// Set a HD chain for the wallet
// TODO: re-enable this and `keypoolsize_hd_internal` check in `wallet_createwallet.py`
// when HD is the default mode (make sure this actually works!)...
// if (!wallet->GenerateNewHDChainEncrypted("", "", passphrase)) {
// throw JSONRPCError(RPC_WALLET_ERROR, "Failed to generate encrypted HD wallet");
// }
// ... and drop this
wallet->UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
wallet->NewKeyPool();
// end TODO
// Relock the wallet
wallet->Lock();
// Empty string means unencrypted
warnings.emplace_back(Untranslated("Empty string given as passphrase, wallet will not be encrypted."));
}
}
AddWallet(wallet);
wallet->postInitProcess();
bilingual_str error;
std::shared_ptr<CWallet> wallet;
WalletCreationStatus status = CreateWallet(*g_rpc_interfaces->chain, passphrase, flags, request.params[0].get_str(), error, warnings, wallet);
switch (status) {
case WalletCreationStatus::CREATION_FAILED:
throw JSONRPCError(RPC_WALLET_ERROR, error.original);
case WalletCreationStatus::ENCRYPTION_FAILED:
throw JSONRPCError(RPC_WALLET_ENCRYPTION_FAILED, error.original);
case WalletCreationStatus::SUCCESS:
break;
// no default case, so the compiler can warn about missing cases
}
UniValue obj(UniValue::VOBJ);
obj.pushKV("name", wallet->GetName());
obj.pushKV("warning", warning);
obj.pushKV("warning", Join(warnings, "\n", OpOriginal));
return obj;
}
@ -3185,10 +3149,10 @@ void FundTransaction(CWallet* const pwallet, CMutableTransaction& tx, CAmount& f
setSubtractFeeFromOutputs.insert(pos);
}
std::string strFailReason;
bilingual_str error;
if (!pwallet->FundTransaction(tx, fee_out, change_position, strFailReason, lockUnspents, setSubtractFeeFromOutputs, coinControl)) {
throw JSONRPCError(RPC_WALLET_ERROR, strFailReason);
if (!pwallet->FundTransaction(tx, fee_out, change_position, error, lockUnspents, setSubtractFeeFromOutputs, coinControl)) {
throw JSONRPCError(RPC_WALLET_ERROR, error.original);
}
}

View File

@ -8,6 +8,7 @@
#include <coinjoin/util.h>
#include <coinjoin/coinjoin.h>
#include <coinjoin/options.h>
#include <util/translation.h>
#include <validation.h>
#include <wallet/wallet.h>
@ -111,7 +112,7 @@ public:
CReserveKey destKey(wallet.get());
CAmount nFeeRet;
int nChangePosRet = -1;
std::string strError;
bilingual_str strError;
CCoinControl coinControl;
CPubKey pubKey;
BOOST_CHECK(destKey.GetReservedKey(pubKey, false));
@ -177,9 +178,9 @@ BOOST_FIXTURE_TEST_CASE(CTransactionBuilderTest, CTransactionBuilderTestSetup)
BOOST_CHECK(!output->UpdateAmount(-1));
BOOST_CHECK_EQUAL(txBuilder.CountOutputs(), 1);
std::string strResult;
bilingual_str strResult;
BOOST_CHECK(txBuilder.Commit(strResult));
CWalletTx& wtx = AddTxToChain(uint256S(strResult));
CWalletTx& wtx = AddTxToChain(uint256S(strResult.original));
BOOST_CHECK_EQUAL(wtx.tx->vout.size(), txBuilder.CountOutputs()); // should have no change output
BOOST_CHECK_EQUAL(wtx.tx->vout[0].nValue, output->GetAmount());
BOOST_CHECK(wtx.tx->vout[0].scriptPubKey == output->GetScript());
@ -189,7 +190,7 @@ BOOST_FIXTURE_TEST_CASE(CTransactionBuilderTest, CTransactionBuilderTestSetup)
CompactTallyItem tallyItem = GetTallyItem({10000, 20000, 30000, 40000, 50000});
CTransactionBuilder txBuilder(wallet, tallyItem);
std::vector<CTransactionBuilderOutput*> vecOutputs;
std::string strResult;
bilingual_str strResult;
auto output = txBuilder.AddOutput(100);
BOOST_CHECK(output != nullptr);
@ -209,7 +210,7 @@ BOOST_FIXTURE_TEST_CASE(CTransactionBuilderTest, CTransactionBuilderTestSetup)
BOOST_CHECK_EQUAL(vecOutputs.size(), 100);
BOOST_CHECK_EQUAL(txBuilder.CountOutputs(), vecOutputs.size());
BOOST_CHECK(txBuilder.Commit(strResult));
CWalletTx& wtx = AddTxToChain(uint256S(strResult));
CWalletTx& wtx = AddTxToChain(uint256S(strResult.original));
BOOST_CHECK_EQUAL(wtx.tx->vout.size(), txBuilder.CountOutputs() + 1); // should have change output
for (const auto& out : wtx.tx->vout) {
auto it = std::find_if(vecOutputs.begin(), vecOutputs.end(), [&](CTransactionBuilderOutput* output) -> bool {

View File

@ -14,6 +14,7 @@
#include <policy/policy.h>
#include <rpc/server.h>
#include <test/util/setup_common.h>
#include <util/translation.h>
#include <validation.h>
#include <wallet/coincontrol.h>
#include <wallet/test/wallet_test_fixture.h>
@ -365,7 +366,7 @@ public:
CTransactionRef tx;
CAmount fee;
int changePos = -1;
std::string error;
bilingual_str error;
CCoinControl dummy;
{
auto locked_chain = m_chain->lock();
@ -525,11 +526,11 @@ public:
CTransactionRef tx;
CAmount nFeeRet;
int nChangePos = nChangePosRequest;
std::string strError;
bilingual_str strError;
auto locked_chain = wallet->chain().lock();
bool fCreationSucceeded = wallet->CreateTransaction(*locked_chain, GetRecipients(vecEntries), tx, nFeeRet, nChangePos, strError, coinControl);
bool fHitMaxTries = strError == strExceededMaxTries;
bool fHitMaxTries = strError.original == strExceededMaxTries;
// This should never happen.
if (fHitMaxTries) {
BOOST_CHECK(!fHitMaxTries);
@ -540,7 +541,7 @@ public:
return false;
}
// Verify the expected error string if there is one provided
if (strErrorExpected.size() && !CheckEqual(strErrorExpected, strError)) {
if (strErrorExpected.size() && !CheckEqual(strErrorExpected, strError.original)) {
return false;
}
if (!fCreateShouldSucceed) {
@ -577,7 +578,7 @@ public:
CTransactionRef tx;
CAmount nFeeRet;
int nChangePosRet = -1;
std::string strError;
bilingual_str strError;
CCoinControl coinControl;
BOOST_CHECK(wallet->CreateTransaction(*wallet->chain().lock(), GetRecipients(vecEntries), tx, nFeeRet, nChangePosRet, strError, coinControl));
wallet->CommitTransaction(tx, {}, {});
@ -912,7 +913,7 @@ BOOST_FIXTURE_TEST_CASE(select_coins_grouped_by_addresses, ListCoinsTestingSetup
CTransactionRef tx2;
CAmount fee;
int changePos = -1;
std::string error;
bilingual_str error;
CCoinControl dummy;
{
auto locked_chain = wallet->chain().lock();

View File

@ -29,6 +29,8 @@
#include <util/error.h>
#include <util/fees.h>
#include <util/moneystr.h>
#include <util/string.h>
#include <util/translation.h>
#include <util/validation.h>
#include <validation.h>
#include <wallet/coincontrol.h>
@ -148,16 +150,16 @@ void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
}
}
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning)
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, bilingual_str& error, std::vector<bilingual_str>& warnings)
{
if (!CWallet::Verify(chain, location, error, warning)) {
error = "Wallet file verification failed: " + error;
if (!CWallet::Verify(chain, location, error, warnings)) {
error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error;
return nullptr;
}
std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location);
std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, error, warnings);
if (!wallet) {
error = "Wallet loading failed.";
error = Untranslated("Wallet loading failed.") + Untranslated(" ") + error;
return nullptr;
}
AddWallet(wallet);
@ -165,9 +167,79 @@ std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocati
return wallet;
}
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, std::string& error, std::string& warning)
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings)
{
return LoadWallet(chain, WalletLocation(name), error, warning);
return LoadWallet(chain, WalletLocation(name), error, warnings);
}
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)
{
// Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET);
// Born encrypted wallets need to be created blank first.
if (!passphrase.empty()) {
wallet_creation_flags |= WALLET_FLAG_BLANK_WALLET;
}
// Check the wallet file location
WalletLocation location(name);
if (location.Exists()) {
error = Untranslated(strprintf("Wallet %s already exists.", location.GetName()));
return WalletCreationStatus::CREATION_FAILED;
}
// Wallet::Verify will check if we're trying to create a wallet with a duplicate name.
if (!CWallet::Verify(chain, location, error, warnings)) {
error = Untranslated("Wallet file verification failed.") + Untranslated(" ") + error;
return WalletCreationStatus::CREATION_FAILED;
}
// Do not allow a passphrase when private keys are disabled
if (!passphrase.empty() && (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
error = Untranslated("Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.");
return WalletCreationStatus::CREATION_FAILED;
}
// Make the wallet
std::shared_ptr<CWallet> wallet = CWallet::CreateWalletFromFile(chain, location, error, warnings, wallet_creation_flags);
if (!wallet) {
error = Untranslated("Wallet creation failed.") + Untranslated(" ") + error;
return WalletCreationStatus::CREATION_FAILED;
}
// Encrypt the wallet
if (!passphrase.empty() && !(wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
if (!wallet->EncryptWallet(passphrase)) {
error = Untranslated("Error: Wallet created but failed to encrypt.");
return WalletCreationStatus::ENCRYPTION_FAILED;
}
if (!create_blank) {
// Unlock the wallet
if (!wallet->Unlock(passphrase)) {
error = Untranslated("Error: Wallet was encrypted but could not be unlocked");
return WalletCreationStatus::ENCRYPTION_FAILED;
}
// Set a HD chain for the wallet
// TODO: re-enable this and `keypoolsize_hd_internal` check in `wallet_createwallet.py`
// when HD is the default mode (make sure this actually works!)...
// if (!wallet->GenerateNewHDChainEncrypted("", "", passphrase)) {
// throw JSONRPCError(RPC_WALLET_ERROR, "Failed to generate encrypted HD wallet");
// }
// ... and drop this
wallet->UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
wallet->NewKeyPool();
// end TODO
// Relock the wallet
wallet->Lock();
}
}
AddWallet(wallet);
wallet->postInitProcess();
result = wallet;
return WalletCreationStatus::SUCCESS;
}
const uint256 CWalletTx::ABANDON_HASH(uint256S("0000000000000000000000000000000000000000000000000000000000000001"));
@ -975,8 +1047,8 @@ bool CWallet::EncryptWallet(const SecureString& strWalletPassphrase)
assert(GetHDChain(hdChainCrypted));
DBG(
tfm::format(std::cout, "EncryptWallet -- current seed: '%s'\n", HexStr(hdChainCurrent.GetSeed()).c_str());
tfm::format(std::cout, "EncryptWallet -- crypted seed: '%s'\n", HexStr(hdChainCrypted.GetSeed()).c_str());
tfm::format(std::cout, "EncryptWallet -- current seed: '%s'\n", HexStr(hdChainCurrent.GetSeed()));
tfm::format(std::cout, "EncryptWallet -- crypted seed: '%s'\n", HexStr(hdChainCrypted.GetSeed()));
);
// ids should match, seed hashes should not
@ -1816,8 +1888,8 @@ bool CWallet::GenerateNewHDChainEncrypted(const SecureString& secureMnemonic, co
assert(res);
DBG(
tfm::format(std::cout, "GenerateNewHDChainEncrypted -- current seed: '%s'\n", HexStr(hdChainTmp.GetSeed()).c_str());
tfm::format(std::cout, "GenerateNewHDChainEncrypted -- crypted seed: '%s'\n", HexStr(hdChainCrypted.GetSeed()).c_str());
tfm::format(std::cout, "GenerateNewHDChainEncrypted -- current seed: '%s'\n", HexStr(hdChainTmp.GetSeed()));
tfm::format(std::cout, "GenerateNewHDChainEncrypted -- crypted seed: '%s'\n", HexStr(hdChainCrypted.GetSeed()));
);
// ids should match, seed hashes should not
@ -2331,7 +2403,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
WalletLogPrintf("Rescan started from block %s...\n", start_block.ToString());
fAbortRescan = false;
ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
ShowProgress(strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), 0); // show rescan progress in GUI as dialog or on splashscreen, if -rescan on startup
uint256 tip_hash;
// The way the 'block_height' is initialized is just a workaround for the gcc bug #47679 since version 4.6.0.
Optional<int> block_height = MakeOptional(false, int());
@ -2350,7 +2422,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
while (block_height && !fAbortRescan && !chain().shutdownRequested()) {
m_scanning_progress = (progress_current - progress_begin) / (progress_end - progress_begin);
if (*block_height % 100 == 0 && progress_end - progress_begin > 0.0) {
ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
ShowProgress(strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), std::max(1, std::min(99, (int)(m_scanning_progress * 100))));
}
if (GetTime() >= nNow + 60) {
nNow = GetTime();
@ -2406,7 +2478,7 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
}
}
}
ShowProgress(strprintf("%s " + _("Rescanning..."), GetDisplayName()), 100); // hide progress dialog in GUI
ShowProgress(strprintf("%s " + _("Rescanning...").translated, GetDisplayName()), 100); // hide progress dialog in GUI
if (block_height && fAbortRescan) {
WalletLogPrintf("Rescan aborted at block %d. Progress=%f\n", *block_height, progress_current);
result.status = ScanResult::USER_ABORT;
@ -3260,7 +3332,7 @@ bool CWallet::SelectCoins(const std::vector<COutput>& vAvailableCoins, const CAm
return res;
}
bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl)
bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl coinControl)
{
std::vector<CRecipient> vecSend;
@ -3287,7 +3359,7 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nC
nExtraPayloadSize = (int)tx.vExtraPayload.size();
CTransactionRef tx_new;
if (!CreateTransaction(*locked_chain, vecSend, tx_new, nFeeRet, nChangePosInOut, strFailReason, coinControl, false, nExtraPayloadSize)) {
if (!CreateTransaction(*locked_chain, vecSend, tx_new, nFeeRet, nChangePosInOut, error, coinControl, false, nExtraPayloadSize)) {
return false;
}
@ -3518,7 +3590,7 @@ std::vector<CompactTallyItem> CWallet::SelectCoinsGroupedByAddresses(bool fSkipD
if (LogAcceptCategory(BCLog::SELECTCOINS)) {
std::string strMessage = "SelectCoinsGroupedByAddresses - vecTallyRet:\n";
for (const auto& item : vecTallyRet)
strMessage += strprintf(" %s %f\n", EncodeDestination(item.txdest).c_str(), float(item.nAmount)/COIN);
strMessage += strprintf(" %s %f\n", EncodeDestination(item.txdest), float(item.nAmount)/COIN);
LogPrint(BCLog::SELECTCOINS, "%s", strMessage); /* Continued */
}
@ -3590,7 +3662,7 @@ bool CWallet::GetBudgetSystemCollateralTX(interfaces::Chain::Lock& locked_chain,
CAmount nFeeRet = 0;
int nChangePosRet = -1;
std::string strFail = "";
bilingual_str error;
std::vector< CRecipient > vecSend;
vecSend.push_back((CRecipient){scriptChange, amount, false});
@ -3598,9 +3670,9 @@ bool CWallet::GetBudgetSystemCollateralTX(interfaces::Chain::Lock& locked_chain,
if (!outpoint.IsNull()) {
coinControl.Select(outpoint);
}
bool success = CreateTransaction(locked_chain, vecSend, tx, nFeeRet, nChangePosRet, strFail, coinControl);
bool success = CreateTransaction(locked_chain, vecSend, tx, nFeeRet, nChangePosRet, error, coinControl);
if(!success){
WalletLogPrintf("CWallet::GetBudgetSystemCollateralTX -- Error: %s\n", strFail);
WalletLogPrintf("CWallet::GetBudgetSystemCollateralTX -- Error: %s\n", error.original);
return false;
}
@ -3608,7 +3680,7 @@ bool CWallet::GetBudgetSystemCollateralTX(interfaces::Chain::Lock& locked_chain,
}
bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet,
int& nChangePosInOut, std::string& strFailReason, const CCoinControl& coin_control, bool sign, int nExtraPayloadSize)
int& nChangePosInOut, bilingual_str& error, const CCoinControl& coin_control, bool sign, int nExtraPayloadSize)
{
CAmount nValue = 0;
CReserveKey reservekey(this);
@ -3618,7 +3690,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
{
if (nValue < 0 || recipient.nAmount < 0)
{
strFailReason = _("Transaction amounts must not be negative");
error = _("Transaction amounts must not be negative");
return false;
}
nValue += recipient.nAmount;
@ -3628,7 +3700,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
}
if (vecSend.empty())
{
strFailReason = _("Transaction must have at least one recipient");
error = _("Transaction must have at least one recipient");
return false;
}
@ -3673,7 +3745,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
// Reserve a new key pair from key pool
if (!CanGetAddresses(true)) {
strFailReason = _("Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.");
error = _("Can't generate a change-address key. No keys in the internal keypool and can't generate any keys.");
return false;
}
CPubKey vchPubKey;
@ -3681,7 +3753,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
ret = reservekey.GetReservedKey(vchPubKey, true);
if (!ret)
{
strFailReason = _("Keypool ran out, please call keypoolrefill first");
error = _("Keypool ran out, please call keypoolrefill first");
return false;
}
@ -3728,12 +3800,12 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
if (recipient.fSubtractFeeFromAmount && nFeeRet > 0)
{
if (txout.nValue < 0)
strFailReason = _("The transaction amount is too small to pay the fee");
error = _("The transaction amount is too small to pay the fee");
else
strFailReason = _("The transaction amount is too small to send after the fee has been deducted");
error = _("The transaction amount is too small to send after the fee has been deducted");
}
else
strFailReason = _("Transaction amount too small");
error = _("Transaction amount too small");
return false;
}
txNew.vout.push_back(txout);
@ -3746,12 +3818,12 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
std::set<CInputCoin> setCoinsTmp;
if (!SelectCoins(vAvailableCoins, nValueToSelect, setCoinsTmp, nValueIn, coin_control, coin_selection_params, bnb_used)) {
if (coin_control.nCoinType == CoinType::ONLY_NONDENOMINATED) {
strFailReason = _("Unable to locate enough non-denominated funds for this transaction.");
error = _("Unable to locate enough non-denominated funds for this transaction.");
} else if (coin_control.nCoinType == CoinType::ONLY_FULLY_MIXED) {
strFailReason = _("Unable to locate enough mixed funds for this transaction.");
strFailReason += " " + strprintf(_("%s uses exact denominated amounts to send funds, you might simply need to mix some more coins."), gCoinJoinName);
error = _("Unable to locate enough mixed funds for this transaction.");
error = error + Untranslated(" ") + strprintf(_("%s uses exact denominated amounts to send funds, you might simply need to mix some more coins."), gCoinJoinName);
} else if (nValueIn < nValueToSelect) {
strFailReason = _("Insufficient funds.");
error = _("Insufficient funds.");
}
return false;
}
@ -3771,7 +3843,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
AssertLockHeld(cs_wallet);
nBytes = CalculateMaximumSignedTxSize(CTransaction(txNew), this, coin_control.fAllowWatchOnly);
if (nBytes < 0) {
strFailReason = _("Signing transaction failed");
error = _("Signing transaction failed");
return false;
}
@ -3782,7 +3854,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
if (nBytes > MAX_STANDARD_TX_SIZE) {
// Do not create oversized transactions (bad-txns-oversize).
strFailReason = _("Transaction too large");
error = _("Transaction too large");
return false;
}
@ -3852,7 +3924,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
}
else if ((unsigned int)nChangePosRequest > txNew.vout.size())
{
strFailReason = _("Change index out of range");
error = _("Change index out of range");
return false;
} else {
nChangePosInOut = nChangePosRequest;
@ -3902,7 +3974,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
if (feeCalc.reason == FeeReason::FALLBACK && !m_allow_fallback_fee) {
// eventually allow a fallback fee
strFailReason = _("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
error = _("Fee estimation failed. Fallbackfee is disabled. Wait a few blocks or enable -fallbackfee.");
return false;
}
@ -3932,7 +4004,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
}
if (nMaxTries == 0) {
strFailReason = _("Exceeded max tries.");
error = _("Exceeded max tries.");
return false;
}
}
@ -3950,7 +4022,7 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
if (!ProduceSignature(*this, MutableTransactionSignatureCreator(&txNew, nIn, coin.txout.nValue, SIGHASH_ALL), scriptPubKey, sigdata))
{
strFailReason = _("Signing transaction failed");
error = _("Signing transaction failed");
return false;
} else {
UpdateInput(txNew.vin.at(nIn), sigdata);
@ -3965,14 +4037,14 @@ bool CWallet::CreateTransaction(interfaces::Chain::Lock& locked_chain, const std
}
if (nFeeRet > m_default_max_tx_fee) {
strFailReason = TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED);
error = Untranslated(TransactionErrorString(TransactionError::MAX_FEE_EXCEEDED));
return false;
}
if (gArgs.GetBoolArg("-walletrejectlongchains", DEFAULT_WALLET_REJECT_LONG_CHAINS)) {
// Lastly, ensure this tx will pass the mempool's chain limits
if (!chain().checkChainLimits(tx)) {
strFailReason = _("Transaction has too long of a mempool chain");
error = _("Transaction has too long of a mempool chain");
return false;
}
}
@ -4330,7 +4402,7 @@ bool CWallet::TopUpKeyPool(unsigned int kpSize)
}
double dProgress = 100.f * m_max_keypool_index / (nTargetSize + 1);
std::string strMsg = strprintf(_("Loading wallet... (%3.2f %%)"), dProgress);
std::string strMsg = strprintf(_("Loading wallet... (%3.2f %%)").translated, dProgress);
uiInterface.InitMessage(strMsg);
}
}
@ -4933,7 +5005,7 @@ std::vector<std::string> CWallet::GetDestValues(const std::string& prefix) const
return values;
}
bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, std::string& error_string, std::string& warning_string)
bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, bilingual_str& error_string, std::vector<bilingual_str>& warnings)
{
// Do some checking on wallet path. It should be either a:
//
@ -4947,17 +5019,17 @@ bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, s
if (!(path_type == fs::file_not_found || path_type == fs::directory_file ||
(path_type == fs::symlink_file && fs::is_directory(wallet_path)) ||
(path_type == fs::regular_file && fs::path(location.GetName()).filename() == location.GetName()))) {
error_string =strprintf(
"Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
"database/log.?????????? files can be stored, a location where such a directory could be created, "
"or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
location.GetName(), GetWalletDir());
error_string = Untranslated(strprintf(
"Invalid -wallet path '%s'. -wallet path should point to a directory where wallet.dat and "
"database/log.?????????? files can be stored, a location where such a directory could be created, "
"or (for backwards compatibility) the name of an existing data file in -walletdir (%s)",
location.GetName(), GetWalletDir()));
return false;
}
// Make sure that the wallet path doesn't clash with an existing wallet path
if (IsWalletLoaded(wallet_path)) {
error_string = strprintf("Error loading wallet %s. Duplicate -wallet filename specified.", location.GetName());
error_string = Untranslated(strprintf("Error loading wallet %s. Duplicate -wallet filename specified.", location.GetName()));
return false;
}
@ -4967,18 +5039,18 @@ bool CWallet::Verify(interfaces::Chain& chain, const WalletLocation& location, s
try {
return database->Verify(error_string);
} catch (const fs::filesystem_error& e) {
error_string = strprintf("Error loading wallet %s. %s", location.GetName(), fsbridge::get_filesystem_error_message(e));
error_string = Untranslated(strprintf("Error loading wallet %s. %s", location.GetName(), fsbridge::get_filesystem_error_message(e)));
return false;
}
// Let tempWallet hold the pointer to the corresponding wallet database.
std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(chain, location, std::move(database));
if (!tempWallet->AutoBackupWallet(wallet_path, warning_string, error_string) && !error_string.empty()) {
if (!tempWallet->AutoBackupWallet(wallet_path, error_string, warnings) && !error_string.original.empty()) {
return false;
}
}
std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags)
std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, bilingual_str& error, std::vector<bilingual_str>& warnings, uint64_t wallet_creation_flags)
{
const std::string walletFile = WalletDataFilePath(location.GetPath()).string();
@ -4986,17 +5058,17 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
std::vector<CWalletTx> vWtx;
if (gArgs.GetBoolArg("-zapwallettxes", false)) {
chain.initMessage(_("Zapping all transactions from wallet..."));
chain.initMessage(_("Zapping all transactions from wallet...").translated);
std::unique_ptr<CWallet> tempWallet = MakeUnique<CWallet>(chain, location, CreateWalletDatabase(location.GetPath()));
DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
if (nZapWalletRet != DBErrors::LOAD_OK) {
chain.initError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
error = strprintf(_("Error loading %s: Wallet corrupted"), walletFile);
return nullptr;
}
}
chain.initMessage(_("Loading wallet..."));
chain.initMessage(_("Loading wallet...").translated);
int64_t nStart = GetTimeMillis();
bool fFirstRun = true;
@ -5004,9 +5076,9 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
// should be possible to use std::allocate_shared.
std::shared_ptr<CWallet> walletInstance(new CWallet(chain, location, CreateWalletDatabase(location.GetPath())), ReleaseWallet);
AddWallet(walletInstance);
auto error = [&](const std::string& strError) {
auto unload_wallet = [&](const bilingual_str& strError) {
RemoveWallet(walletInstance);
chain.initError(strError);
error = strError;
return nullptr;
};
DBErrors nLoadWalletRet;
@ -5019,23 +5091,23 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
if (nLoadWalletRet != DBErrors::LOAD_OK)
{
if (nLoadWalletRet == DBErrors::CORRUPT) {
return error(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
return unload_wallet(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
}
else if (nLoadWalletRet == DBErrors::NONCRITICAL_ERROR)
{
chain.initWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
" or address book entries might be missing or incorrect."),
warnings.push_back(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
" or address book entries might be missing or incorrect."),
walletFile));
}
else if (nLoadWalletRet == DBErrors::TOO_NEW) {
return error(strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, PACKAGE_NAME));
return unload_wallet(strprintf(_("Error loading %s: Wallet requires newer version of %s"), walletFile, PACKAGE_NAME));
}
else if (nLoadWalletRet == DBErrors::NEED_REWRITE)
{
return error(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), PACKAGE_NAME));
return unload_wallet(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), PACKAGE_NAME));
}
else {
return error(strprintf(_("Error loading %s"), walletFile));
return unload_wallet(strprintf(_("Error loading %s"), walletFile));
}
}
@ -5053,7 +5125,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
walletInstance->WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
if (nMaxVersion < walletInstance->GetVersion())
{
return error(_("Cannot downgrade wallet"));
return unload_wallet(_("Cannot downgrade wallet"));
}
walletInstance->SetMaxVersion(nMaxVersion);
}
@ -5074,10 +5146,10 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
CHDChain newHdChain;
std::vector<unsigned char> vchSeed = ParseHex(strSeed);
if (!newHdChain.SetSeed(SecureVector(vchSeed.begin(), vchSeed.end()), true)) {
return error(strprintf(_("%s failed"), "SetSeed"));
return unload_wallet(strprintf(_("%s failed"), "SetSeed"));
}
if (!walletInstance->SetHDChainSingle(newHdChain, false)) {
return error(strprintf(_("%s failed"), "SetHDChainSingle"));
return unload_wallet(strprintf(_("%s failed"), "SetHDChainSingle"));
}
// add default account
newHdChain.AddAccount();
@ -5104,58 +5176,54 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
// Top up the keypool
if (walletInstance->CanGenerateKeys() && !walletInstance->TopUpKeyPool()) {
return error(_("Unable to generate initial keys"));
return unload_wallet(_("Unable to generate initial keys"));
}
auto locked_chain = chain.lock();
walletInstance->ChainStateFlushed(locked_chain->getTipLocator());
// Try to create wallet backup right after new wallet was created
std::string strBackupWarning;
std::string strBackupError;
if(!walletInstance->AutoBackupWallet("", strBackupWarning, strBackupError)) {
if (!strBackupWarning.empty()) {
chain.initWarning(strBackupWarning);
}
if (!strBackupError.empty()) {
return error(strBackupError);
bilingual_str strBackupError;
if(!walletInstance->AutoBackupWallet("", strBackupError, warnings)) {
if (!strBackupError.original.empty()) {
return unload_wallet(strBackupError);
}
}
} else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
// Make it impossible to disable private keys after creation
chain.initError(strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile));
error = strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile);
return NULL;
} else if (walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
LOCK(walletInstance->cs_KeyStore);
if (!walletInstance->mapKeys.empty() || !walletInstance->mapCryptedKeys.empty()) {
chain.initWarning(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
warnings.push_back(strprintf(_("Warning: Private keys detected in wallet {%s} with disabled private keys"), walletFile));
}
}
else if (gArgs.IsArgSet("-usehd")) {
bool useHD = gArgs.GetBoolArg("-usehd", DEFAULT_USE_HD_WALLET);
if (walletInstance->IsHDEnabled() && !useHD) {
return error(strprintf(_("Error loading %s: You can't disable HD on an already existing HD wallet"),
return unload_wallet(strprintf(_("Error loading %s: You can't disable HD on an already existing HD wallet"),
walletInstance->GetName()));
}
if (!walletInstance->IsHDEnabled() && useHD) {
return error(strprintf(_("Error loading %s: You can't enable HD on an already existing non-HD wallet"),
return unload_wallet(strprintf(_("Error loading %s: You can't enable HD on an already existing non-HD wallet"),
walletInstance->GetName()));
}
}
// Warn user every time a non-encrypted HD wallet is started
if (walletInstance->IsHDEnabled() && !walletInstance->IsLocked()) {
SetMiscWarning(_("Make sure to encrypt your wallet and delete all non-encrypted backups after you have verified that the wallet works!"));
SetMiscWarning(_("Make sure to encrypt your wallet and delete all non-encrypted backups after you have verified that the wallet works!").translated);
}
if (gArgs.IsArgSet("-mintxfee")) {
CAmount n = 0;
if (!ParseMoney(gArgs.GetArg("-mintxfee", ""), n) || 0 == n) {
chain.initError(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")));
error = Untranslated(AmountErrMsg("mintxfee", gArgs.GetArg("-mintxfee", "")));
return nullptr;
}
if (n > HIGH_TX_FEE_PER_KB) {
chain.initWarning(AmountHighWarn("-mintxfee") + " " +
warnings.push_back(Untranslated(AmountHighWarn("-mintxfee")) + Untranslated(" ") +
_("This is the minimum transaction fee you pay on every transaction."));
}
walletInstance->m_min_fee = CFeeRate(n);
@ -5165,11 +5233,11 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
if (gArgs.IsArgSet("-fallbackfee")) {
CAmount nFeePerK = 0;
if (!ParseMoney(gArgs.GetArg("-fallbackfee", ""), nFeePerK)) {
chain.initError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), gArgs.GetArg("-fallbackfee", "")));
error = strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), gArgs.GetArg("-fallbackfee", ""));
return nullptr;
}
if (nFeePerK > HIGH_TX_FEE_PER_KB) {
chain.initWarning(AmountHighWarn("-fallbackfee") + " " +
warnings.push_back(Untranslated(AmountHighWarn("-fallbackfee")) + Untranslated(" ") +
_("This is the transaction fee you may pay when fee estimates are not available."));
}
walletInstance->m_fallback_fee = CFeeRate(nFeePerK);
@ -5178,11 +5246,11 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
if (gArgs.IsArgSet("-discardfee")) {
CAmount nFeePerK = 0;
if (!ParseMoney(gArgs.GetArg("-discardfee", ""), nFeePerK)) {
chain.initError(strprintf(_("Invalid amount for -discardfee=<amount>: '%s'"), gArgs.GetArg("-discardfee", "")));
error = strprintf(_("Invalid amount for -discardfee=<amount>: '%s'"), gArgs.GetArg("-discardfee", ""));
return nullptr;
}
if (nFeePerK > HIGH_TX_FEE_PER_KB) {
chain.initWarning(AmountHighWarn("-discardfee") + " " +
warnings.push_back(Untranslated(AmountHighWarn("-discardfee")) + Untranslated(" ") +
_("This is the transaction fee you may discard if change is smaller than dust at this level"));
}
walletInstance->m_discard_rate = CFeeRate(nFeePerK);
@ -5190,41 +5258,40 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
if (gArgs.IsArgSet("-paytxfee")) {
CAmount nFeePerK = 0;
if (!ParseMoney(gArgs.GetArg("-paytxfee", ""), nFeePerK)) {
chain.initError(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")));
error = Untranslated(AmountErrMsg("paytxfee", gArgs.GetArg("-paytxfee", "")));
return nullptr;
}
if (nFeePerK > HIGH_TX_FEE_PER_KB) {
chain.initWarning(AmountHighWarn("-paytxfee") + " " +
warnings.push_back(Untranslated(AmountHighWarn("-paytxfee")) + Untranslated(" ") +
_("This is the transaction fee you will pay if you send a transaction."));
}
walletInstance->m_pay_tx_fee = CFeeRate(nFeePerK, 1000);
if (walletInstance->m_pay_tx_fee < chain.relayMinFee()) {
chain.initError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString()));
error = strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString());
return nullptr;
}
}
if (gArgs.IsArgSet("-maxtxfee"))
{
if (gArgs.IsArgSet("-maxtxfee")) {
CAmount nMaxFee = 0;
if (!ParseMoney(gArgs.GetArg("-maxtxfee", ""), nMaxFee)) {
chain.initError(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")));
error = Untranslated(AmountErrMsg("maxtxfee", gArgs.GetArg("-maxtxfee", "")));
return nullptr;
}
if (nMaxFee > HIGH_MAX_TX_FEE) {
chain.initWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
warnings.push_back(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
}
if (CFeeRate(nMaxFee, 1000) < chain.relayMinFee()) {
chain.initError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
gArgs.GetArg("-maxtxfee", ""), chain.relayMinFee().ToString()));
error = strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
gArgs.GetArg("-maxtxfee", ""), chain.relayMinFee().ToString());
return nullptr;
}
walletInstance->m_default_max_tx_fee = nMaxFee;
}
if (chain.relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB)
chain.initWarning(AmountHighWarn("-minrelaytxfee") + " " +
warnings.push_back(Untranslated(AmountHighWarn("-minrelaytxfee")) + Untranslated(" ") +
_("The wallet will avoid paying less than the minimum relay fee."));
walletInstance->m_confirm_target = gArgs.GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
@ -5272,11 +5339,11 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
}
if (rescan_height != block_height) {
return error(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"));
return unload_wallet(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"));
}
}
chain.initMessage(_("Rescanning..."));
chain.initMessage(_("Rescanning...").translated);
walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
// No need to read and scan block if block was created before
@ -5293,7 +5360,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
{
WalletRescanReserver reserver(walletInstance.get());
if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(locked_chain->getBlockHash(rescan_height), {} /* stop block */, reserver, true /* update */).status)) {
return error(_("Failed to rescan the wallet during initialization"));
return unload_wallet(_("Failed to rescan the wallet during initialization"));
}
}
walletInstance->ChainStateFlushed(locked_chain->getTipLocator());
@ -5378,9 +5445,8 @@ bool CWallet::BackupWallet(const std::string& strDest)
// This should be called carefully:
// either supply the actual wallet_path to make a raw copy of wallet.dat or "" to backup current instance via BackupWallet()
bool CWallet::AutoBackupWallet(const fs::path& wallet_path, std::string& strBackupWarningRet, std::string& strBackupErrorRet)
bool CWallet::AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error_string, std::vector<bilingual_str>& warnings)
{
strBackupWarningRet = strBackupErrorRet = "";
std::string strWalletName = GetName();
if (strWalletName.empty()) {
strWalletName = "wallet.dat";
@ -5400,15 +5466,15 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, std::string& strBack
WalletLogPrintf("Creating backup folder %s\n", backupsDir.string());
if(!fs::create_directories(backupsDir)) {
// something is wrong, we shouldn't continue until it's resolved
strBackupErrorRet = strprintf(_("Wasn't able to create wallet backup folder %s!"), backupsDir.string());
WalletLogPrintf("%s\n", strBackupErrorRet);
error_string = strprintf(_("Wasn't able to create wallet backup folder %s!"), backupsDir.string());
WalletLogPrintf("%s\n", error_string.translated);
nWalletBackups = -1;
return false;
}
} else if (!fs::is_directory(backupsDir)) {
// something is wrong, we shouldn't continue until it's resolved
strBackupErrorRet = strprintf(_("%s is not a valid backup folder!"), backupsDir.string());
WalletLogPrintf("%s\n", strBackupErrorRet);
error_string = strprintf(_("%s is not a valid backup folder!"), backupsDir.string());
WalletLogPrintf("%s\n", error_string.translated);
nWalletBackups = -1;
return false;
}
@ -5430,8 +5496,8 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, std::string& strBack
fs::path backupFile = backupsDir / (strWalletName + dateTimeStr);
backupFile.make_preferred();
if (!BackupWallet(backupFile.string())) {
strBackupWarningRet = strprintf(_("Failed to create backup %s!"), backupFile.string());
WalletLogPrintf("%s\n", strBackupWarningRet);
warnings.push_back(strprintf(_("Failed to create backup %s!"), backupFile.string()));
WalletLogPrintf("%s\n", Join(warnings, "\n", OpTranslated));
nWalletBackups = -1;
return false;
}
@ -5440,8 +5506,8 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, std::string& strBack
nKeysLeftSinceAutoBackup = KeypoolCountExternalKeys();
WalletLogPrintf("nKeysLeftSinceAutoBackup: %d\n", nKeysLeftSinceAutoBackup);
if (IsLocked(true)) {
strBackupWarningRet = _("Wallet is locked, can't replenish keypool! Automatic backups and mixing are disabled, please unlock your wallet to replenish keypool.");
WalletLogPrintf("%s\n", strBackupWarningRet);
warnings.push_back(_("Wallet is locked, can't replenish keypool! Automatic backups and mixing are disabled, please unlock your wallet to replenish keypool."));
WalletLogPrintf("%s\n", Join(warnings, "\n", OpTranslated));
nWalletBackups = -2;
return false;
}
@ -5455,8 +5521,8 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, std::string& strBack
backupFile.make_preferred();
if (fs::exists(backupFile))
{
strBackupWarningRet = _("Failed to create backup, file already exists! This could happen if you restarted wallet in less than 60 seconds. You can continue if you are ok with this.");
WalletLogPrintf("%s\n", strBackupWarningRet);
warnings.push_back(_("Failed to create backup, file already exists! This could happen if you restarted wallet in less than 60 seconds. You can continue if you are ok with this."));
WalletLogPrintf("%s\n", Join(warnings, "\n", OpTranslated));
return false;
}
if(fs::exists(sourceFile)) {
@ -5464,8 +5530,8 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, std::string& strBack
fs::copy_file(sourceFile, backupFile);
WalletLogPrintf("Creating backup of %s -> %s\n", sourceFile.string(), backupFile.string());
} catch(fs::filesystem_error &error) {
strBackupWarningRet = strprintf(_("Failed to create backup, error: %s"), fsbridge::get_filesystem_error_message(error));
WalletLogPrintf("%s\n", strBackupWarningRet);
warnings.push_back(strprintf(_("Failed to create backup, error: %s"), fsbridge::get_filesystem_error_message(error)));
WalletLogPrintf("%s\n", Join(warnings, "\n", OpTranslated));
nWalletBackups = -1;
return false;
}
@ -5503,8 +5569,8 @@ bool CWallet::AutoBackupWallet(const fs::path& wallet_path, std::string& strBack
fs::remove(file.second);
WalletLogPrintf("Old backup deleted: %s\n", file.second);
} catch(fs::filesystem_error &error) {
strBackupWarningRet = strprintf(_("Failed to delete backup, error: %s"), fsbridge::get_filesystem_error_message(error));
WalletLogPrintf("%s\n", strBackupWarningRet);
warnings.push_back(strprintf(_("Failed to delete backup, error: %s"), fsbridge::get_filesystem_error_message(error)));
WalletLogPrintf("%s\n", Join(warnings, "\n", OpTranslated));
return false;
}
}

View File

@ -38,6 +38,8 @@
#include <utility>
#include <vector>
struct bilingual_str;
//! Explicitly unload and delete the wallet.
// Blocks the current thread after signaling the unload intent so that all
// wallet clients release the wallet.
@ -50,7 +52,15 @@ bool RemoveWallet(const std::shared_ptr<CWallet>& wallet);
bool HasWallets();
std::vector<std::shared_ptr<CWallet>> GetWallets();
std::shared_ptr<CWallet> GetWallet(const std::string& name);
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, std::string& error, std::string& warning);
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, bilingual_str& error, std::vector<bilingual_str>& warnings);
enum class WalletCreationStatus {
SUCCESS,
CREATION_FAILED,
ENCRYPTION_FAILED
};
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);
static const unsigned int DEFAULT_KEYPOOL_SIZE = 1000;
//! -paytxfee default
@ -984,7 +994,7 @@ public:
* Insert additional inputs into the transaction by
* calling CreateTransaction();
*/
bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, std::string& strFailReason, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl);
bool FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, bool lockUnspents, const std::set<int>& setSubtractFeeFromOutputs, CCoinControl);
bool SignTransaction(CMutableTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
/**
@ -993,7 +1003,7 @@ public:
* @note passing nChangePosInOut as -1 will result in setting a random position
*/
bool CreateTransaction(interfaces::Chain::Lock& locked_chain, const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut,
std::string& strFailReason, const CCoinControl& coin_control, bool sign = true, int nExtraPayloadSize = 0);
bilingual_str& error, const CCoinControl& coin_control, bool sign = true, int nExtraPayloadSize = 0);
/**
* Submit the transaction to the node's mempool and then relay to peers.
* Should be called after CreateTransaction unless you want to abort
@ -1175,10 +1185,10 @@ public:
bool AbandonTransaction(interfaces::Chain::Lock& locked_chain, const uint256& hashTx);
//! Verify wallet naming and perform salvage on the wallet if required
static bool Verify(interfaces::Chain& chain, const WalletLocation& location, std::string& error_string, std::string& warning_string);
static bool Verify(interfaces::Chain& chain, const WalletLocation& location, bilingual_str& error_string, std::vector<bilingual_str>& warnings);
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
static std::shared_ptr<CWallet> CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, uint64_t wallet_creation_flags = 0);
static std::shared_ptr<CWallet> CreateWalletFromFile(interfaces::Chain& chain, const WalletLocation& location, bilingual_str& error, std::vector<bilingual_str>& warnings, uint64_t wallet_creation_flags = 0);
/**
* Wallet post-init setup
@ -1188,7 +1198,7 @@ public:
/* AutoBackup functionality */
static bool InitAutoBackup();
bool AutoBackupWallet(const fs::path& wallet_path, std::string& strBackupWarningRet, std::string& strBackupErrorRet);
bool AutoBackupWallet(const fs::path& wallet_path, bilingual_str& error_string, std::vector<bilingual_str>& warnings);
bool BackupWallet(const std::string& strDest);

View File

@ -4,6 +4,7 @@
#include <fs.h>
#include <interfaces/chain.h>
#include <util/translation.h>
#include <util/system.h>
#include <wallet/salvage.h>
#include <wallet/wallet.h>
@ -112,14 +113,14 @@ static bool SalvageWallet(const fs::path& path)
std::unique_ptr<WalletDatabase> database = CreateWalletDatabase(path);
// Initialize the environment before recovery
std::string error_string;
bilingual_str error_string;
try {
database->Verify(error_string);
} catch (const fs::filesystem_error& e) {
error_string = strprintf("Error loading wallet. %s", fsbridge::get_filesystem_error_message(e));
error_string = Untranslated(strprintf("Error loading wallet. %s", fsbridge::get_filesystem_error_message(e)));
}
if (!error_string.empty()) {
tfm::format(std::cerr, "Failed to open wallet for salvage :%s\n", error_string);
if (!error_string.original.empty()) {
tfm::format(std::cerr, "Failed to open wallet for salvage :%s\n", error_string.translated);
return false;
}

View File

@ -3,9 +3,11 @@
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <warnings.h>
#include <sync.h>
#include <util/system.h>
#include <warnings.h>
#include <util/translation.h>
#include <hash.h>
static Mutex g_warnings_mutex;
@ -47,7 +49,7 @@ std::string GetWarnings(const std::string& strFor)
if (!CLIENT_VERSION_IS_RELEASE) {
strStatusBar = "This is a pre-release test build - use at your own risk - do not use for mining or merchant applications";
strGUI = _("This is a pre-release test build - use at your own risk - do not use for mining or merchant applications");
strGUI = _("This is a pre-release test build - use at your own risk - do not use for mining or merchant applications").translated;
}
// Misc warnings like out of disk space and clock is wrong
@ -60,12 +62,12 @@ std::string GetWarnings(const std::string& strFor)
if (fLargeWorkForkFound)
{
strStatusBar = "Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.";
strGUI += (strGUI.empty() ? "" : uiAlertSeparator) + _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.");
strGUI += (strGUI.empty() ? "" : uiAlertSeparator) + _("Warning: The network does not appear to fully agree! Some miners appear to be experiencing issues.").translated;
}
else if (fLargeWorkInvalidChainFound)
{
strStatusBar = "Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.";
strGUI += (strGUI.empty() ? "" : uiAlertSeparator) + _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.");
strGUI += (strGUI.empty() ? "" : uiAlertSeparator) + _("Warning: We do not appear to fully agree with our peers! You may need to upgrade, or other nodes may need to upgrade.").translated;
}
if (strFor == "gui")

View File

@ -22,7 +22,7 @@ class ConfArgsTest(BitcoinTestFramework):
conf.write('includeconf={}\n'.format(inc_conf_file_path))
self.nodes[0].assert_start_raises_init_error(
expected_msg='Error parsing command line arguments: Invalid parameter -dash_cli',
expected_msg='Error: Error parsing command line arguments: Invalid parameter -dash_cli',
extra_args=['-dash_cli=1'],
)
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
@ -33,7 +33,7 @@ class ConfArgsTest(BitcoinTestFramework):
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('-dash=1\n')
self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 1: -dash=1, options in configuration file must be specified without leading -')
self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Error reading configuration file: parse error on line 1: -dash=1, options in configuration file must be specified without leading -')
if self.is_wallet_compiled():
with open(inc_conf_file_path, 'w', encoding='utf8') as conf:
@ -47,19 +47,19 @@ class ConfArgsTest(BitcoinTestFramework):
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('nono\n')
self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 1: nono, if you intended to specify a negated option, use nono=1 instead')
self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Error reading configuration file: parse error on line 1: nono, if you intended to specify a negated option, use nono=1 instead')
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('server=1\nrpcuser=someuser\nrpcpassword=some#pass')
self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided')
self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided')
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('server=1\nrpcuser=someuser\nmain.rpcpassword=some#pass')
self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided')
self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Error reading configuration file: parse error on line 3, using # in rpcpassword can be ambiguous and should be avoided')
with open(inc_conf_file_path, 'w', encoding='utf-8') as conf:
conf.write('server=1\nrpcuser=someuser\n[main]\nrpcpassword=some#pass')
self.nodes[0].assert_start_raises_init_error(expected_msg='Error reading configuration file: parse error on line 4, using # in rpcpassword can be ambiguous and should be avoided')
self.nodes[0].assert_start_raises_init_error(expected_msg='Error: Error reading configuration file: parse error on line 4, using # in rpcpassword can be ambiguous and should be avoided')
inc_conf_file2_path = os.path.join(self.nodes[0].datadir, 'include2.conf')
with open(os.path.join(self.nodes[0].datadir, 'dash.conf'), 'a', encoding='utf-8') as conf:

View File

@ -43,7 +43,7 @@ class IncludeConfTest(BitcoinTestFramework):
self.log.info("-includeconf cannot be used as command-line arg")
self.stop_node(0)
self.nodes[0].assert_start_raises_init_error(extra_args=["-includeconf=relative2.conf"], expected_msg="Error parsing command line arguments: -includeconf cannot be used from commandline; -includeconf=relative2.conf")
self.nodes[0].assert_start_raises_init_error(extra_args=["-includeconf=relative2.conf"], expected_msg="Error: Error parsing command line arguments: -includeconf cannot be used from commandline; -includeconf=relative2.conf")
self.log.info("-includeconf cannot be used recursively. subversion should end with 'main; relative)/'")
with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "a", encoding="utf8") as f:
@ -59,11 +59,11 @@ class IncludeConfTest(BitcoinTestFramework):
# Commented out as long as we ignore invalid arguments in configuration files
#with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f:
# f.write("foo=bar\n")
#self.nodes[0].assert_start_raises_init_error(expected_msg="Error reading configuration file: Invalid configuration value foo")
#self.nodes[0].assert_start_raises_init_error(expected_msg="Error: Error reading configuration file: Invalid configuration value foo")
self.log.info("-includeconf cannot be invalid path")
os.remove(os.path.join(self.options.tmpdir, "node0", "relative.conf"))
self.nodes[0].assert_start_raises_init_error(expected_msg="Error reading configuration file: Failed to include configuration file relative.conf")
self.nodes[0].assert_start_raises_init_error(expected_msg="Error: Error reading configuration file: Failed to include configuration file relative.conf")
self.log.info("multiple -includeconf args can be used from the base config file. subversion should end with 'main; relative; relative2)/'")
with open(os.path.join(self.options.tmpdir, "node0", "relative.conf"), "w", encoding="utf8") as f:

View File

@ -118,8 +118,21 @@ class CreateWalletTest(BitcoinTestFramework):
# TODO: re-enable this when HD is the default mode
# assert_equal(walletinfo['keypoolsize_hd_internal'], 1)
# end TODO
# Empty passphrase, error
assert_raises_rpc_error(-16, 'Cannot encrypt a wallet with a blank password', self.nodes[0].createwallet, 'w7', False, False, '')
# Allow empty passphrase, but there should be a warning
resp = self.nodes[0].createwallet(wallet_name='w7', disable_private_keys=False, blank=False, passphrase='')
assert_equal(resp['warning'], 'Empty string given as passphrase, wallet will not be encrypted.')
w7 = node.get_wallet_rpc('w7')
assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 10)
# TODO: renable this when avoid reuse flag is added
# self.log.info('Test making a wallet with avoid reuse flag')
# self.nodes[0].createwallet('w8', False, False, '', True) # Use positional arguments to check for bug where avoid_reuse could not be set for wallets without needing them to be encrypted
# w8 = node.get_wallet_rpc('w8')
# assert_raises_rpc_error(-15, 'Error: running with an unencrypted wallet, but walletpassphrase was called.', w7.walletpassphrase, '', 10)
# assert_equal(w8.getwalletinfo()["avoid_reuse"], True)
self.log.info('Using a passphrase with private keys disabled returns error')
assert_raises_rpc_error(-4, 'Passphrase provided but private keys are disabled. A passphrase is only used to encrypt private keys, so cannot be used for wallets with private keys disabled.', self.nodes[0].createwallet, wallet_name='w9', disable_private_keys=True, passphrase='thisisapassphrase')
if __name__ == '__main__':
CreateWalletTest().main()

View File

@ -230,10 +230,10 @@ class MultiWalletTest(BitcoinTestFramework):
assert_raises_rpc_error(-18, 'Wallet wallets not found.', self.nodes[0].loadwallet, 'wallets')
# Fail to load duplicate wallets
assert_raises_rpc_error(-4, 'Wallet file verification failed: Error loading wallet w1. Duplicate -wallet filename specified.', self.nodes[0].loadwallet, wallet_names[0])
assert_raises_rpc_error(-4, 'Wallet file verification failed. Error loading wallet w1. Duplicate -wallet filename specified.', self.nodes[0].loadwallet, wallet_names[0])
# Fail to load duplicate wallets by different ways (directory and filepath)
assert_raises_rpc_error(-4, "Wallet file verification failed: Error loading wallet wallet.dat. Duplicate -wallet filename specified.", self.nodes[0].loadwallet, 'wallet.dat')
assert_raises_rpc_error(-4, "Wallet file verification failed. Error loading wallet wallet.dat. Duplicate -wallet filename specified.", self.nodes[0].loadwallet, 'wallet.dat')
# Fail to load if one wallet is a copy of another
assert_raises_rpc_error(-1, "BerkeleyBatch: Can't open database w8_copy (duplicates fileid", self.nodes[0].loadwallet, 'w8_copy')
@ -244,7 +244,7 @@ class MultiWalletTest(BitcoinTestFramework):
# Fail to load if wallet file is a symlink
if os.name != 'nt':
assert_raises_rpc_error(-4, "Wallet file verification failed: Invalid -wallet path 'w8_symlink'", self.nodes[0].loadwallet, 'w8_symlink')
assert_raises_rpc_error(-4, "Wallet file verification failed. Invalid -wallet path 'w8_symlink'", self.nodes[0].loadwallet, 'w8_symlink')
self.log.info("Test dynamic wallet creation.")
@ -340,14 +340,10 @@ class MultiWalletTest(BitcoinTestFramework):
self.log.info("Fail -upgradewallet that results in downgrade")
assert_raises_rpc_error(
-4,
"Wallet loading failed.",
'Wallet loading failed. Error loading {}: Wallet requires newer version of {}'.format(
wallet_dir('high_minversion', 'wallet.dat'), "Dash Core"),
lambda: self.nodes[0].loadwallet(filename='high_minversion'),
)
self.stop_node(
i=0,
expected_stderr='Error: Error loading {}: Wallet requires newer version of Dash Core'.format(
wallet_dir('high_minversion', 'wallet.dat')),
)
if __name__ == '__main__':

View File

@ -24,7 +24,7 @@ FALSE_POSITIVES = [
("src/stacktraces.cpp", "strprintf(fmtStr, i, si.pc, lstr, fstr)"),
("src/statsd_client.cpp", "snprintf(d->errmsg, sizeof(d->errmsg), \"could not create socket, err=%m\")"),
("src/statsd_client.cpp", "snprintf(d->errmsg, sizeof(d->errmsg), \"sendto server fail, host=%s:%d, err=%m\", d->host.c_str(), d->port)"),
("src/util/system.cpp", "strprintf(_(COPYRIGHT_HOLDERS), COPYRIGHT_HOLDERS_SUBSTITUTION)"),
("src/util/system.cpp", "strprintf(_(COPYRIGHT_HOLDERS).translated, COPYRIGHT_HOLDERS_SUBSTITUTION)"),
("src/wallet/wallet.h", "WalletLogPrintf(std::string fmt, Params... parameters)"),
("src/wallet/wallet.h", "LogPrintf((\"%s \" + fmt).c_str(), GetDisplayName(), parameters...)"),
("src/logging.h", "LogPrintf(const char* fmt, const Args&... args)"),