|
|
@@ -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() |