Browse Source

Merge #7691: [Wallet] refactor wallet/init interaction

25340b7 [Wallet] refactor wallet/init interaction (Jonas Schnelli)
tags/v0.15.1
Wladimir J. van der Laan 4 years ago
parent
commit
30c2dd8d05
No account linked to committer's email address
5 changed files with 118 additions and 125 deletions
  1. 5
    81
      src/init.cpp
  2. 0
    2
      src/init.h
  3. 0
    1
      src/test/test_bitcoin.cpp
  4. 105
    38
      src/wallet/wallet.cpp
  5. 8
    3
      src/wallet/wallet.h

+ 5
- 81
src/init.cpp View File

@@ -65,9 +65,6 @@

using namespace std;

#ifdef ENABLE_WALLET
CWallet* pwalletMain = NULL;
#endif
bool fFeeEstimatesInitialized = false;
static const bool DEFAULT_PROXYRANDOMIZE = true;
static const bool DEFAULT_REST_ENABLE = false;
@@ -948,56 +945,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
nBytesPerSigOp = GetArg("-bytespersigop", nBytesPerSigOp);

#ifdef ENABLE_WALLET
if (mapArgs.count("-mintxfee"))
{
CAmount n = 0;
if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
CWallet::minTxFee = CFeeRate(n);
else
return InitError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"]));
}
if (mapArgs.count("-fallbackfee"))
{
CAmount nFeePerK = 0;
if (!ParseMoney(mapArgs["-fallbackfee"], nFeePerK))
return InitError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), mapArgs["-fallbackfee"]));
if (nFeePerK > HIGH_TX_FEE_PER_KB)
InitWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available."));
CWallet::fallbackFee = CFeeRate(nFeePerK);
}
if (mapArgs.count("-paytxfee"))
{
CAmount nFeePerK = 0;
if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK))
return InitError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"]));
if (nFeePerK > HIGH_TX_FEE_PER_KB)
InitWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
payTxFee = CFeeRate(nFeePerK, 1000);
if (payTxFee < ::minRelayTxFee)
{
return InitError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
mapArgs["-paytxfee"], ::minRelayTxFee.ToString()));
}
}
if (mapArgs.count("-maxtxfee"))
{
CAmount nMaxFee = 0;
if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee))
return InitError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"]));
if (nMaxFee > HIGH_MAX_TX_FEE)
InitWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
maxTxFee = nMaxFee;
if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
{
return InitError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
mapArgs["-maxtxfee"], ::minRelayTxFee.ToString()));
}
}
nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS);

std::string strWalletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);
if (!CWallet::ParameterInteraction())
return false;
#endif // ENABLE_WALLET

fIsBareMultisigStd = GetBoolArg("-permitbaremultisig", DEFAULT_PERMIT_BAREMULTISIG);
@@ -1032,11 +981,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
return InitError(strprintf(_("Initialization sanity check failed. %s is shutting down."), _(PACKAGE_NAME)));

std::string strDataDir = GetDataDir().string();
#ifdef ENABLE_WALLET
// Wallet file must be a plain filename without a directory
if (strWalletFile != boost::filesystem::basename(strWalletFile) + boost::filesystem::extension(strWalletFile))
return InitError(strprintf(_("Wallet %s resides outside data directory %s"), strWalletFile, strDataDir));
#endif

// Make sure only a single Bitcoin process is using the data directory.
boost::filesystem::path pathLockFile = GetDataDir() / ".lock";
FILE* file = fopen(pathLockFile.string().c_str(), "a"); // empty lock file; created if it doesn't exist.
@@ -1097,20 +1042,8 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
// ********************************************************* Step 5: verify wallet database integrity
#ifdef ENABLE_WALLET
if (!fDisableWallet) {
LogPrintf("Using wallet %s\n", strWalletFile);
uiInterface.InitMessage(_("Verifying wallet..."));

std::string warningString;
std::string errorString;

if (!CWallet::Verify(strWalletFile, warningString, errorString))
if (!CWallet::Verify())
return false;

if (!warningString.empty())
InitWarning(warningString);
if (!errorString.empty())
return InitError(errorString);

} // (!fDisableWallet)
#endif // ENABLE_WALLET
// ********************************************************* Step 6: network initialization
@@ -1421,16 +1354,7 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
pwalletMain = NULL;
LogPrintf("Wallet disabled!\n");
} else {
std::string warningString;
std::string errorString;
pwalletMain = CWallet::InitLoadWallet(fDisableWallet, strWalletFile, warningString, errorString);
if (!warningString.empty())
InitWarning(warningString);
if (!errorString.empty())
{
LogPrintf("%s", errorString);
return InitError(errorString);
}
CWallet::InitLoadWallet();
if (!pwalletMain)
return false;
}

+ 0
- 2
src/init.h View File

@@ -16,8 +16,6 @@ namespace boost
class thread_group;
} // namespace boost

extern CWallet* pwalletMain;

void StartShutdown();
bool ShutdownRequested();
/** Interrupt threads */

+ 0
- 1
src/test/test_bitcoin.cpp View File

@@ -31,7 +31,6 @@
#include <boost/thread.hpp>

CClientUIInterface uiInterface; // Declared but not defined in ui_interface.h
CWallet* pwalletMain;

extern bool fPrintToConsole;
extern void noui_connect();

+ 105
- 38
src/wallet/wallet.cpp View File

@@ -33,6 +33,7 @@

using namespace std;

CWallet* pwalletMain = NULL;
/** Transaction fee set by the user */
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE);
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET;
@@ -364,8 +365,33 @@ void CWallet::Flush(bool shutdown)
bitdb.Flush(shutdown);
}

bool CWallet::Verify(const string& walletFile, string& warningString, string& errorString)
bool static UIError(const std::string &str)
{
uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_ERROR);
return false;
}

void static UIWarning(const std::string &str)
{
uiInterface.ThreadSafeMessageBox(str, "", CClientUIInterface::MSG_WARNING);
}

static std::string AmountErrMsg(const char * const optname, const std::string& strValue)
{
return strprintf(_("Invalid amount for -%s=<amount>: '%s'"), optname, strValue);
}

bool CWallet::Verify()
{
std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);

LogPrintf("Using wallet %s\n", walletFile);
uiInterface.InitMessage(_("Verifying wallet..."));

// Wallet file must be a plain filename without a directory
if (walletFile != boost::filesystem::basename(walletFile) + boost::filesystem::extension(walletFile))
return UIError(strprintf(_("Wallet %s resides outside data directory %s"), walletFile, GetDataDir().string()));

if (!bitdb.Open(GetDataDir()))
{
// try moving the database env out of the way
@@ -381,9 +407,7 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er
// try again
if (!bitdb.Open(GetDataDir())) {
// if it still fails, it probably means we can't even create the database env
string msg = strprintf(_("Error initializing wallet database environment %s!"), GetDataDir());
errorString += msg;
return true;
return UIError(strprintf(_("Error initializing wallet database environment %s!"), GetDataDir()));
}
}
@@ -399,14 +423,14 @@ bool CWallet::Verify(const string& walletFile, string& warningString, string& er
CDBEnv::VerifyResult r = bitdb.Verify(walletFile, CWalletDB::Recover);
if (r == CDBEnv::RECOVER_OK)
{
warningString += strprintf(_("Warning: Wallet file corrupt, data salvaged!"
UIWarning(strprintf(_("Warning: Wallet file corrupt, data salvaged!"
" Original %s saved as %s in %s; if"
" your balance or transactions are incorrect you should"
" restore from a backup."),
walletFile, "wallet.{timestamp}.bak", GetDataDir());
walletFile, "wallet.{timestamp}.bak", GetDataDir()));
}
if (r == CDBEnv::RECOVER_FAIL)
errorString += strprintf(_("%s corrupt, salvage failed"), walletFile);
return UIError(strprintf(_("%s corrupt, salvage failed"), walletFile));
}
return true;
@@ -3018,20 +3042,20 @@ std::string CWallet::GetWalletHelpString(bool showDebug)
return strUsage;
}

CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWalletFile, std::string& warningString, std::string& errorString)
bool CWallet::InitLoadWallet()
{
std::string walletFile = GetArg("-wallet", DEFAULT_WALLET_DAT);

// needed to restore wallet transaction meta data after -zapwallettxes
std::vector<CWalletTx> vWtx;

if (GetBoolArg("-zapwallettxes", false)) {
uiInterface.InitMessage(_("Zapping all transactions from wallet..."));

CWallet *tempWallet = new CWallet(strWalletFile);
CWallet *tempWallet = new CWallet(walletFile);
DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx);
if (nZapWalletRet != DB_LOAD_OK) {
errorString = strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile);
uiInterface.InitMessage(strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile));
return NULL;
return UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
}

delete tempWallet;
@@ -3042,32 +3066,27 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall

int64_t nStart = GetTimeMillis();
bool fFirstRun = true;
CWallet *walletInstance = new CWallet(strWalletFile);
CWallet *walletInstance = new CWallet(walletFile);
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
if (nLoadWalletRet != DB_LOAD_OK)
{
if (nLoadWalletRet == DB_CORRUPT)
errorString += strprintf(_("Error loading %s: Wallet corrupted"), strWalletFile) + "\n";
return UIError(strprintf(_("Error loading %s: Wallet corrupted"), walletFile));
else if (nLoadWalletRet == DB_NONCRITICAL_ERROR)
{
warningString += strprintf(_("Error reading %s! All keys read correctly, but transaction data"
UIWarning(strprintf(_("Error reading %s! All keys read correctly, but transaction data"
" or address book entries might be missing or incorrect."),
strWalletFile);
walletFile));
}
else if (nLoadWalletRet == DB_TOO_NEW)
errorString += strprintf(_("Error loading %s: Wallet requires newer version of %s"),
strWalletFile, _(PACKAGE_NAME)) +
"\n";
return UIError(strprintf(_("Error loading %s: Wallet requires newer version of %s"),
walletFile, _(PACKAGE_NAME)));
else if (nLoadWalletRet == DB_NEED_REWRITE)
{
errorString += strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)) + "\n";
LogPrintf("%s", errorString);
return UIError(strprintf(_("Wallet needed to be rewritten: restart %s to complete"), _(PACKAGE_NAME)));
}
else
errorString += strprintf(_("Error loading %s"), strWalletFile) + "\n";

if (!errorString.empty())
return NULL;
return UIError(strprintf(_("Error loading %s"), walletFile));
}

if (GetBoolArg("-upgradewallet", fFirstRun))
@@ -3083,8 +3102,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
if (nMaxVersion < walletInstance->GetVersion())
{
errorString += _("Cannot downgrade wallet") + "\n";
return NULL;
return UIError(_("Cannot downgrade wallet"));
}
walletInstance->SetMaxVersion(nMaxVersion);
}
@@ -3098,10 +3116,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
if (walletInstance->GetKeyFromPool(newDefaultKey)) {
walletInstance->SetDefaultKey(newDefaultKey);
if (!walletInstance->SetAddressBook(walletInstance->vchDefaultKey.GetID(), "", "receive"))
{
errorString += _("Cannot write default address") += "\n";
return NULL;
}
return UIError(_("Cannot write default address") += "\n");
}

walletInstance->SetBestChain(chainActive.GetLocator());
@@ -3116,7 +3131,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
pindexRescan = chainActive.Genesis();
else
{
CWalletDB walletdb(strWalletFile);
CWalletDB walletdb(walletFile);
CBlockLocator locator;
if (walletdb.ReadBestBlock(locator))
pindexRescan = FindForkInGlobalIndex(chainActive, locator);
@@ -3135,10 +3150,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
block = block->pprev;

if (pindexRescan != block)
{
errorString = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
return NULL;
}
return UIError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"));
}

uiInterface.InitMessage(_("Rescanning..."));
@@ -3152,7 +3164,7 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
// Restore wallet transaction metadata after -zapwallettxes=1
if (GetBoolArg("-zapwallettxes", false) && GetArg("-zapwallettxes", "1") != "2")
{
CWalletDB walletdb(strWalletFile);
CWalletDB walletdb(walletFile);

BOOST_FOREACH(const CWalletTx& wtxOld, vWtx)
{
@@ -3176,7 +3188,62 @@ CWallet* CWallet::InitLoadWallet(bool fDisableWallet, const std::string& strWall
}
walletInstance->SetBroadcastTransactions(GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));

return walletInstance;
pwalletMain = walletInstance;
return true;
}

bool CWallet::ParameterInteraction()
{
if (mapArgs.count("-mintxfee"))
{
CAmount n = 0;
if (ParseMoney(mapArgs["-mintxfee"], n) && n > 0)
CWallet::minTxFee = CFeeRate(n);
else
return UIError(AmountErrMsg("mintxfee", mapArgs["-mintxfee"]));
}
if (mapArgs.count("-fallbackfee"))
{
CAmount nFeePerK = 0;
if (!ParseMoney(mapArgs["-fallbackfee"], nFeePerK))
return UIError(strprintf(_("Invalid amount for -fallbackfee=<amount>: '%s'"), mapArgs["-fallbackfee"]));
if (nFeePerK > HIGH_TX_FEE_PER_KB)
UIWarning(_("-fallbackfee is set very high! This is the transaction fee you may pay when fee estimates are not available."));
CWallet::fallbackFee = CFeeRate(nFeePerK);
}
if (mapArgs.count("-paytxfee"))
{
CAmount nFeePerK = 0;
if (!ParseMoney(mapArgs["-paytxfee"], nFeePerK))
return UIError(AmountErrMsg("paytxfee", mapArgs["-paytxfee"]));
if (nFeePerK > HIGH_TX_FEE_PER_KB)
UIWarning(_("-paytxfee is set very high! This is the transaction fee you will pay if you send a transaction."));
payTxFee = CFeeRate(nFeePerK, 1000);
if (payTxFee < ::minRelayTxFee)
{
return UIError(strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
mapArgs["-paytxfee"], ::minRelayTxFee.ToString()));
}
}
if (mapArgs.count("-maxtxfee"))
{
CAmount nMaxFee = 0;
if (!ParseMoney(mapArgs["-maxtxfee"], nMaxFee))
return UIError(AmountErrMsg("maxtxfee", mapArgs["-maxtxfee"]));
if (nMaxFee > HIGH_MAX_TX_FEE)
UIWarning(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
maxTxFee = nMaxFee;
if (CFeeRate(maxTxFee, 1000) < ::minRelayTxFee)
{
return UIError(strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
mapArgs["-maxtxfee"], ::minRelayTxFee.ToString()));
}
}
nTxConfirmTarget = GetArg("-txconfirmtarget", DEFAULT_TX_CONFIRM_TARGET);
bSpendZeroConfChange = GetBoolArg("-spendzeroconfchange", DEFAULT_SPEND_ZEROCONF_CHANGE);
fSendFreeTransactions = GetBoolArg("-sendfreetransactions", DEFAULT_SEND_FREE_TRANSACTIONS);

return true;
}

CKeyPool::CKeyPool()

+ 8
- 3
src/wallet/wallet.h View File

@@ -28,6 +28,8 @@

#include <boost/shared_ptr.hpp>

extern CWallet* pwalletMain;

/**
* Settings
*/
@@ -841,7 +843,7 @@ public:
void Flush(bool shutdown=false);

//! Verify the wallet database and perform salvage if required
static bool Verify(const std::string& walletFile, std::string& warningString, std::string& errorString);
static bool Verify();
/**
* Address book entry changed.
@@ -876,8 +878,11 @@ public:
/* Returns the wallets help message */
static std::string GetWalletHelpString(bool showDebug);

/* initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
static CWallet* InitLoadWallet(bool fDisableWallet, const std::string& strWalletFile, std::string& warningString, std::string& errorString);
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
static bool InitLoadWallet();

/* Wallets parameter interaction */
static bool ParameterInteraction();
};

/** A key allocated from the key pool. */

Loading…
Cancel
Save