Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show All 36 Lines | |||||
#include <boost/algorithm/string/replace.hpp> | #include <boost/algorithm/string/replace.hpp> | ||||
#include <algorithm> | #include <algorithm> | ||||
#include <cassert> | #include <cassert> | ||||
#include <future> | #include <future> | ||||
static CCriticalSection cs_wallets; | static CCriticalSection cs_wallets; | ||||
static std::vector<CWallet *> vpwallets GUARDED_BY(cs_wallets); | static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets); | ||||
bool AddWallet(CWallet *wallet) { | bool AddWallet(const std::shared_ptr<CWallet> &wallet) { | ||||
LOCK(cs_wallets); | LOCK(cs_wallets); | ||||
assert(wallet); | assert(wallet); | ||||
std::vector<CWallet *>::const_iterator i = | std::vector<std::shared_ptr<CWallet>>::const_iterator i = | ||||
std::find(vpwallets.begin(), vpwallets.end(), wallet); | std::find(vpwallets.begin(), vpwallets.end(), wallet); | ||||
if (i != vpwallets.end()) { | if (i != vpwallets.end()) { | ||||
return false; | return false; | ||||
} | } | ||||
vpwallets.push_back(wallet); | vpwallets.push_back(wallet); | ||||
return true; | return true; | ||||
} | } | ||||
bool RemoveWallet(CWallet *wallet) { | bool RemoveWallet(const std::shared_ptr<CWallet> &wallet) { | ||||
LOCK(cs_wallets); | LOCK(cs_wallets); | ||||
assert(wallet); | assert(wallet); | ||||
std::vector<CWallet *>::iterator i = | std::vector<std::shared_ptr<CWallet>>::iterator i = | ||||
std::find(vpwallets.begin(), vpwallets.end(), wallet); | std::find(vpwallets.begin(), vpwallets.end(), wallet); | ||||
if (i == vpwallets.end()) { | if (i == vpwallets.end()) { | ||||
return false; | return false; | ||||
} | } | ||||
vpwallets.erase(i); | vpwallets.erase(i); | ||||
return true; | return true; | ||||
} | } | ||||
bool HasWallets() { | bool HasWallets() { | ||||
LOCK(cs_wallets); | LOCK(cs_wallets); | ||||
return !vpwallets.empty(); | return !vpwallets.empty(); | ||||
} | } | ||||
std::vector<CWallet *> GetWallets() { | std::vector<std::shared_ptr<CWallet>> GetWallets() { | ||||
LOCK(cs_wallets); | LOCK(cs_wallets); | ||||
return vpwallets; | return vpwallets; | ||||
} | } | ||||
CWallet *GetWallet(const std::string &name) { | std::shared_ptr<CWallet> GetWallet(const std::string &name) { | ||||
LOCK(cs_wallets); | LOCK(cs_wallets); | ||||
for (CWallet *wallet : vpwallets) { | for (const std::shared_ptr<CWallet> &wallet : vpwallets) { | ||||
if (wallet->GetName() == name) { | if (wallet->GetName() == name) { | ||||
return wallet; | return wallet; | ||||
} | } | ||||
} | } | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
static const size_t OUTPUT_GROUP_MAX_ENTRIES = 10; | static const size_t OUTPUT_GROUP_MAX_ENTRIES = 10; | ||||
▲ Show 20 Lines • Show All 3,330 Lines • ▼ Show 20 Lines | DBErrors CWallet::LoadWallet(bool &fFirstRunRet) { | ||||
fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && | fFirstRunRet = mapKeys.empty() && mapCryptedKeys.empty() && | ||||
mapWatchKeys.empty() && setWatchOnly.empty() && | mapWatchKeys.empty() && setWatchOnly.empty() && | ||||
mapScripts.empty(); | mapScripts.empty(); | ||||
if (nLoadWalletRet != DBErrors::LOAD_OK) { | if (nLoadWalletRet != DBErrors::LOAD_OK) { | ||||
return nLoadWalletRet; | return nLoadWalletRet; | ||||
} | } | ||||
uiInterface.LoadWallet(this); | |||||
return DBErrors::LOAD_OK; | return DBErrors::LOAD_OK; | ||||
} | } | ||||
DBErrors CWallet::ZapSelectTx(std::vector<TxId> &txIdsIn, | DBErrors CWallet::ZapSelectTx(std::vector<TxId> &txIdsIn, | ||||
std::vector<TxId> &txIdsOut) { | std::vector<TxId> &txIdsOut) { | ||||
// mapWallet | // mapWallet | ||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
DBErrors nZapSelectTxRet = | DBErrors nZapSelectTxRet = | ||||
▲ Show 20 Lines • Show All 861 Lines • ▼ Show 20 Lines | if (salvage_wallet) { | ||||
return false; | return false; | ||||
} | } | ||||
} | } | ||||
return WalletBatch::VerifyDatabaseFile(wallet_path, warning_string, | return WalletBatch::VerifyDatabaseFile(wallet_path, warning_string, | ||||
error_string); | error_string); | ||||
} | } | ||||
CWallet *CWallet::CreateWalletFromFile(const CChainParams &chainParams, | std::shared_ptr<CWallet> | ||||
const std::string &name, | CWallet::CreateWalletFromFile(const CChainParams &chainParams, | ||||
const fs::path &path) { | const std::string &name, const fs::path &path) { | ||||
const std::string &walletFile = name; | const std::string &walletFile = name; | ||||
// Needed to restore wallet transaction meta data after -zapwallettxes | // Needed to restore wallet transaction meta data after -zapwallettxes | ||||
std::vector<CWalletTx> vWtx; | std::vector<CWalletTx> vWtx; | ||||
if (gArgs.GetBoolArg("-zapwallettxes", false)) { | if (gArgs.GetBoolArg("-zapwallettxes", false)) { | ||||
uiInterface.InitMessage(_("Zapping all transactions from wallet...")); | uiInterface.InitMessage(_("Zapping all transactions from wallet...")); | ||||
std::unique_ptr<CWallet> tempWallet = std::make_unique<CWallet>( | std::unique_ptr<CWallet> tempWallet = std::make_unique<CWallet>( | ||||
chainParams, name, WalletDatabase::Create(path)); | chainParams, name, WalletDatabase::Create(path)); | ||||
DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); | DBErrors nZapWalletRet = tempWallet->ZapWalletTx(vWtx); | ||||
if (nZapWalletRet != DBErrors::LOAD_OK) { | if (nZapWalletRet != DBErrors::LOAD_OK) { | ||||
InitError( | InitError( | ||||
strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); | strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
uiInterface.InitMessage(_("Loading wallet...")); | uiInterface.InitMessage(_("Loading wallet...")); | ||||
int64_t nStart = GetTimeMillis(); | int64_t nStart = GetTimeMillis(); | ||||
bool fFirstRun = true; | bool fFirstRun = true; | ||||
// Make a temporary wallet unique pointer so memory doesn't get leaked if | std::shared_ptr<CWallet> walletInstance = std::make_shared<CWallet>( | ||||
// wallet creation fails. | chainParams, name, WalletDatabase::Create(path)); | ||||
auto temp_wallet = std::make_unique<CWallet>(chainParams, name, | |||||
WalletDatabase::Create(path)); | |||||
CWallet *walletInstance = temp_wallet.get(); | |||||
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); | DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun); | ||||
if (nLoadWalletRet != DBErrors::LOAD_OK) { | if (nLoadWalletRet != DBErrors::LOAD_OK) { | ||||
if (nLoadWalletRet == DBErrors::CORRUPT) { | if (nLoadWalletRet == DBErrors::CORRUPT) { | ||||
InitError( | InitError( | ||||
strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); | strprintf(_("Error loading %s: Wallet corrupted"), walletFile)); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
Show All 14 Lines | if (nLoadWalletRet != DBErrors::LOAD_OK) { | ||||
_(PACKAGE_NAME))); | _(PACKAGE_NAME))); | ||||
return nullptr; | return nullptr; | ||||
} else { | } else { | ||||
InitError(strprintf(_("Error loading %s"), walletFile)); | InitError(strprintf(_("Error loading %s"), walletFile)); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
uiInterface.LoadWallet(walletInstance); | |||||
if (gArgs.GetBoolArg("-upgradewallet", fFirstRun)) { | if (gArgs.GetBoolArg("-upgradewallet", fFirstRun)) { | ||||
int nMaxVersion = gArgs.GetArg("-upgradewallet", 0); | int nMaxVersion = gArgs.GetArg("-upgradewallet", 0); | ||||
// The -upgradewallet without argument case | // The -upgradewallet without argument case | ||||
if (nMaxVersion == 0) { | if (nMaxVersion == 0) { | ||||
LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST); | LogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST); | ||||
nMaxVersion = CLIENT_VERSION; | nMaxVersion = CLIENT_VERSION; | ||||
// permanently upgrade the wallet immediately | // permanently upgrade the wallet immediately | ||||
walletInstance->SetMinVersion(FEATURE_LATEST); | walletInstance->SetMinVersion(FEATURE_LATEST); | ||||
▲ Show 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | if (chainActive.Tip() && chainActive.Tip() != pindexRescan) { | ||||
while (pindexRescan && walletInstance->nTimeFirstKey && | while (pindexRescan && walletInstance->nTimeFirstKey && | ||||
(pindexRescan->GetBlockTime() < | (pindexRescan->GetBlockTime() < | ||||
(walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW))) { | (walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW))) { | ||||
pindexRescan = chainActive.Next(pindexRescan); | pindexRescan = chainActive.Next(pindexRescan); | ||||
} | } | ||||
nStart = GetTimeMillis(); | nStart = GetTimeMillis(); | ||||
{ | { | ||||
WalletRescanReserver reserver(walletInstance); | WalletRescanReserver reserver(walletInstance.get()); | ||||
if (!reserver.reserve()) { | if (!reserver.reserve()) { | ||||
InitError( | InitError( | ||||
_("Failed to rescan the wallet during initialization")); | _("Failed to rescan the wallet during initialization")); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, | walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, | ||||
reserver, true); | reserver, true); | ||||
} | } | ||||
Show All 23 Lines | if (chainActive.Tip() && chainActive.Tip() != pindexRescan) { | ||||
batch.WriteTx(*copyTo); | batch.WriteTx(*copyTo); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
// Register with the validation interface. It's ok to do this after rescan | // Register with the validation interface. It's ok to do this after rescan | ||||
// since we're still holding cs_main. | // since we're still holding cs_main. | ||||
RegisterValidationInterface(temp_wallet.release()); | RegisterValidationInterface(walletInstance.get()); | ||||
walletInstance->SetBroadcastTransactions( | walletInstance->SetBroadcastTransactions( | ||||
gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); | gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST)); | ||||
LOCK(walletInstance->cs_wallet); | LOCK(walletInstance->cs_wallet); | ||||
LogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize()); | LogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize()); | ||||
LogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size()); | LogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size()); | ||||
LogPrintf("mapAddressBook.size() = %u\n", | LogPrintf("mapAddressBook.size() = %u\n", | ||||
▲ Show 20 Lines • Show All 183 Lines • Show Last 20 Lines |