Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show First 20 Lines • Show All 273 Lines • ▼ Show 20 Lines | const CWalletTx *CWallet::GetWalletTx(const TxId &txid) const { | ||||
} | } | ||||
return &(it->second); | return &(it->second); | ||||
} | } | ||||
CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal) { | CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal) { | ||||
assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)); | assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)); | ||||
assert(!IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET)); | assert(!IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET)); | ||||
// mapKeyMetadata | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
// default to compressed public keys if we want 0.6.0 wallets | // default to compressed public keys if we want 0.6.0 wallets | ||||
bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); | bool fCompressed = CanSupportFeature(FEATURE_COMPRPUBKEY); | ||||
CKey secret; | CKey secret; | ||||
// Create new metadata | // Create new metadata | ||||
int64_t nCreationTime = GetTime(); | int64_t nCreationTime = GetTime(); | ||||
▲ Show 20 Lines • Show All 98 Lines • ▼ Show 20 Lines | void CWallet::DeriveNewChildKey(WalletBatch &batch, CKeyMetadata &metadata, | ||||
if (!batch.WriteHDChain(hdChain)) { | if (!batch.WriteHDChain(hdChain)) { | ||||
throw std::runtime_error(std::string(__func__) + | throw std::runtime_error(std::string(__func__) + | ||||
": Writing HD chain model failed"); | ": Writing HD chain model failed"); | ||||
} | } | ||||
} | } | ||||
bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &secret, | bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey &secret, | ||||
const CPubKey &pubkey) { | const CPubKey &pubkey) { | ||||
// mapKeyMetadata | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
// Make sure we aren't adding private keys to private key disabled wallets | // Make sure we aren't adding private keys to private key disabled wallets | ||||
assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)); | assert(!IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS)); | ||||
// FillableSigningProvider has no concept of wallet databases, but calls | // FillableSigningProvider has no concept of wallet databases, but calls | ||||
// AddCryptedKey which is overridden below. To avoid flushes, the database | // AddCryptedKey which is overridden below. To avoid flushes, the database | ||||
// handle is tunneled through to it. | // handle is tunneled through to it. | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | if (encrypted_batch) { | ||||
vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); | vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); | ||||
} | } | ||||
return WalletBatch(*database).WriteCryptedKey( | return WalletBatch(*database).WriteCryptedKey( | ||||
vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); | vchPubKey, vchCryptedSecret, mapKeyMetadata[vchPubKey.GetID()]); | ||||
} | } | ||||
void CWallet::LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &meta) { | void CWallet::LoadKeyMetadata(const CKeyID &keyID, const CKeyMetadata &meta) { | ||||
// mapKeyMetadata | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
UpdateTimeFirstKey(meta.nCreateTime); | UpdateTimeFirstKey(meta.nCreateTime); | ||||
mapKeyMetadata[keyID] = meta; | mapKeyMetadata[keyID] = meta; | ||||
} | } | ||||
void CWallet::LoadScriptMetadata(const CScriptID &script_id, | void CWallet::LoadScriptMetadata(const CScriptID &script_id, | ||||
const CKeyMetadata &meta) { | const CKeyMetadata &meta) { | ||||
// m_script_metadata | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
UpdateTimeFirstKey(meta.nCreateTime); | UpdateTimeFirstKey(meta.nCreateTime); | ||||
m_script_metadata[script_id] = meta; | m_script_metadata[script_id] = meta; | ||||
} | } | ||||
void CWallet::UpgradeKeyMetadata() { | void CWallet::UpgradeKeyMetadata() { | ||||
// mapKeyMetadata | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
if (IsLocked() || IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) { | if (IsLocked() || IsWalletFlagSet(WALLET_FLAG_KEY_ORIGIN_METADATA)) { | ||||
return; | return; | ||||
} | } | ||||
auto batch = std::make_unique<WalletBatch>(*database); | auto batch = std::make_unique<WalletBatch>(*database); | ||||
for (auto &meta_pair : mapKeyMetadata) { | for (auto &meta_pair : mapKeyMetadata) { | ||||
CKeyMetadata &meta = meta_pair.second; | CKeyMetadata &meta = meta_pair.second; | ||||
▲ Show 20 Lines • Show All 275 Lines • ▼ Show 20 Lines | |||||
void CWallet::ChainStateFlushed(const CBlockLocator &loc) { | void CWallet::ChainStateFlushed(const CBlockLocator &loc) { | ||||
WalletBatch batch(*database); | WalletBatch batch(*database); | ||||
batch.WriteBestBlock(loc); | batch.WriteBestBlock(loc); | ||||
} | } | ||||
void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch *batch_in, | void CWallet::SetMinVersion(enum WalletFeature nVersion, WalletBatch *batch_in, | ||||
bool fExplicit) { | bool fExplicit) { | ||||
// nWalletVersion | |||||
LOCK(cs_wallet); | LOCK(cs_wallet); | ||||
if (nWalletVersion >= nVersion) { | if (nWalletVersion >= nVersion) { | ||||
return; | return; | ||||
} | } | ||||
// When doing an explicit upgrade, if we pass the max version permitted, | // When doing an explicit upgrade, if we pass the max version permitted, | ||||
// upgrade all the way. | // upgrade all the way. | ||||
if (fExplicit && nVersion > nWalletMaxVersion) { | if (fExplicit && nVersion > nWalletMaxVersion) { | ||||
Show All 11 Lines | if (nWalletVersion > 40000) { | ||||
batch->WriteMinVersion(nWalletVersion); | batch->WriteMinVersion(nWalletVersion); | ||||
} | } | ||||
if (!batch_in) { | if (!batch_in) { | ||||
delete batch; | delete batch; | ||||
} | } | ||||
} | } | ||||
bool CWallet::SetMaxVersion(int nVersion) { | bool CWallet::SetMaxVersion(int nVersion) { | ||||
// nWalletVersion, nWalletMaxVersion | |||||
LOCK(cs_wallet); | LOCK(cs_wallet); | ||||
// Cannot downgrade below current version | // Cannot downgrade below current version | ||||
if (nWalletVersion > nVersion) { | if (nWalletVersion > nVersion) { | ||||
return false; | return false; | ||||
} | } | ||||
nWalletMaxVersion = nVersion; | nWalletMaxVersion = nVersion; | ||||
▲ Show 20 Lines • Show All 296 Lines • ▼ Show 20 Lines | DBErrors CWallet::ReorderTransactions() { | ||||
} | } | ||||
batch.WriteOrderPosNext(nOrderPosNext); | batch.WriteOrderPosNext(nOrderPosNext); | ||||
return DBErrors::LOAD_OK; | return DBErrors::LOAD_OK; | ||||
} | } | ||||
int64_t CWallet::IncOrderPosNext(WalletBatch *batch) { | int64_t CWallet::IncOrderPosNext(WalletBatch *batch) { | ||||
// nOrderPosNext | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
int64_t nRet = nOrderPosNext++; | int64_t nRet = nOrderPosNext++; | ||||
if (batch) { | if (batch) { | ||||
batch->WriteOrderPosNext(nOrderPosNext); | batch->WriteOrderPosNext(nOrderPosNext); | ||||
} else { | } else { | ||||
WalletBatch(*database).WriteOrderPosNext(nOrderPosNext); | WalletBatch(*database).WriteOrderPosNext(nOrderPosNext); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 1,963 Lines • ▼ Show 20 Lines | bool CWallet::SelectCoins(const std::vector<COutput> &vAvailableCoins, | ||||
// Add preset inputs to the total value selected. | // Add preset inputs to the total value selected. | ||||
nValueRet += nValueFromPresetInputs; | nValueRet += nValueFromPresetInputs; | ||||
return res; | return res; | ||||
} | } | ||||
bool CWallet::SignTransaction(CMutableTransaction &tx) { | bool CWallet::SignTransaction(CMutableTransaction &tx) { | ||||
AssertLockHeld(cs_wallet); | |||||
// sign the new tx | // sign the new tx | ||||
int nIn = 0; | int nIn = 0; | ||||
for (CTxIn &input : tx.vin) { | for (CTxIn &input : tx.vin) { | ||||
auto mi = mapWallet.find(input.prevout.GetTxId()); | auto mi = mapWallet.find(input.prevout.GetTxId()); | ||||
if (mi == mapWallet.end() || | if (mi == mapWallet.end() || | ||||
input.prevout.GetN() >= mi->second.tx->vout.size()) { | input.prevout.GetN() >= mi->second.tx->vout.size()) { | ||||
return false; | return false; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 617 Lines • ▼ Show 20 Lines | if (nLoadWalletRet != DBErrors::LOAD_OK) { | ||||
return nLoadWalletRet; | return nLoadWalletRet; | ||||
} | } | ||||
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 | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
DBErrors nZapSelectTxRet = | DBErrors nZapSelectTxRet = | ||||
WalletBatch(*database, "cr+").ZapSelectTx(txIdsIn, txIdsOut); | WalletBatch(*database, "cr+").ZapSelectTx(txIdsIn, txIdsOut); | ||||
for (const TxId &txid : txIdsOut) { | for (const TxId &txid : txIdsOut) { | ||||
const auto &it = mapWallet.find(txid); | const auto &it = mapWallet.find(txid); | ||||
wtxOrdered.erase(it->second.m_it_wtxOrdered); | wtxOrdered.erase(it->second.m_it_wtxOrdered); | ||||
mapWallet.erase(it); | mapWallet.erase(it); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 139 Lines • ▼ Show 20 Lines | if (!TopUpKeyPool()) { | ||||
return false; | return false; | ||||
} | } | ||||
WalletLogPrintf("CWallet::NewKeyPool rewrote keypool\n"); | WalletLogPrintf("CWallet::NewKeyPool rewrote keypool\n"); | ||||
return true; | return true; | ||||
} | } | ||||
size_t CWallet::KeypoolCountExternalKeys() { | size_t CWallet::KeypoolCountExternalKeys() { | ||||
// setExternalKeyPool | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
return setExternalKeyPool.size() + set_pre_split_keypool.size(); | return setExternalKeyPool.size() + set_pre_split_keypool.size(); | ||||
} | } | ||||
void CWallet::LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) { | void CWallet::LoadKeyPool(int64_t nIndex, const CKeyPool &keypool) { | ||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
if (keypool.m_pre_split) { | if (keypool.m_pre_split) { | ||||
set_pre_split_keypool.insert(nIndex); | set_pre_split_keypool.insert(nIndex); | ||||
▲ Show 20 Lines • Show All 305 Lines • ▼ Show 20 Lines | for (const auto &walletEntry : mapWallet) { | ||||
balances[addr] += n; | balances[addr] += n; | ||||
} | } | ||||
} | } | ||||
return balances; | return balances; | ||||
} | } | ||||
std::set<std::set<CTxDestination>> CWallet::GetAddressGroupings() { | std::set<std::set<CTxDestination>> CWallet::GetAddressGroupings() { | ||||
// mapWallet | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
std::set<std::set<CTxDestination>> groupings; | std::set<std::set<CTxDestination>> groupings; | ||||
std::set<CTxDestination> grouping; | std::set<CTxDestination> grouping; | ||||
for (const auto &walletEntry : mapWallet) { | for (const auto &walletEntry : mapWallet) { | ||||
const CWalletTx &wtx = walletEntry.second; | const CWalletTx &wtx = walletEntry.second; | ||||
if (wtx.tx->vin.size() > 0) { | if (wtx.tx->vin.size() > 0) { | ||||
▲ Show 20 Lines • Show All 181 Lines • ▼ Show 20 Lines | while (it != std::end(*setKeyPool)) { | ||||
LearnAllRelatedScripts(keypool.vchPubKey); | LearnAllRelatedScripts(keypool.vchPubKey); | ||||
batch.ErasePool(index); | batch.ErasePool(index); | ||||
WalletLogPrintf("keypool index %d removed\n", index); | WalletLogPrintf("keypool index %d removed\n", index); | ||||
it = setKeyPool->erase(it); | it = setKeyPool->erase(it); | ||||
} | } | ||||
} | } | ||||
void CWallet::LockCoin(const COutPoint &output) { | void CWallet::LockCoin(const COutPoint &output) { | ||||
// setLockedCoins | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
setLockedCoins.insert(output); | setLockedCoins.insert(output); | ||||
} | } | ||||
void CWallet::UnlockCoin(const COutPoint &output) { | void CWallet::UnlockCoin(const COutPoint &output) { | ||||
// setLockedCoins | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
setLockedCoins.erase(output); | setLockedCoins.erase(output); | ||||
} | } | ||||
void CWallet::UnlockAllCoins() { | void CWallet::UnlockAllCoins() { | ||||
// setLockedCoins | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
setLockedCoins.clear(); | setLockedCoins.clear(); | ||||
} | } | ||||
bool CWallet::IsLockedCoin(const COutPoint &outpoint) const { | bool CWallet::IsLockedCoin(const COutPoint &outpoint) const { | ||||
// setLockedCoins | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
return setLockedCoins.count(outpoint) > 0; | return setLockedCoins.count(outpoint) > 0; | ||||
} | } | ||||
void CWallet::ListLockedCoins(std::vector<COutPoint> &vOutpts) const { | void CWallet::ListLockedCoins(std::vector<COutPoint> &vOutpts) const { | ||||
// setLockedCoins | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
for (COutPoint outpoint : setLockedCoins) { | for (COutPoint outpoint : setLockedCoins) { | ||||
vOutpts.push_back(outpoint); | vOutpts.push_back(outpoint); | ||||
} | } | ||||
} | } | ||||
/** @} */ // end of Actions | /** @} */ // end of Actions | ||||
void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock &locked_chain, | void CWallet::GetKeyBirthTimes(interfaces::Chain::Lock &locked_chain, | ||||
std::map<CKeyID, int64_t> &mapKeyBirth) const { | std::map<CKeyID, int64_t> &mapKeyBirth) const { | ||||
// mapKeyMetadata | |||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
mapKeyBirth.clear(); | mapKeyBirth.clear(); | ||||
// Get birth times for keys with metadata. | // Get birth times for keys with metadata. | ||||
for (const auto &entry : mapKeyMetadata) { | for (const auto &entry : mapKeyMetadata) { | ||||
if (entry.second.nCreateTime) { | if (entry.second.nCreateTime) { | ||||
mapKeyBirth[entry.first] = entry.second.nCreateTime; | mapKeyBirth[entry.first] = entry.second.nCreateTime; | ||||
} | } | ||||
▲ Show 20 Lines • Show All 313 Lines • ▼ Show 20 Lines | if (nLoadWalletRet != DBErrors::LOAD_OK) { | ||||
return nullptr; | return nullptr; | ||||
} else { | } else { | ||||
chain.initError( | chain.initError( | ||||
strprintf(_("Error loading %s").translated, walletFile)); | strprintf(_("Error loading %s").translated, walletFile)); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
int prev_version = walletInstance->nWalletVersion; | int prev_version = walletInstance->GetVersion(); | ||||
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) { | ||||
walletInstance->WalletLogPrintf("Performing wallet upgrade to %i\n", | walletInstance->WalletLogPrintf("Performing wallet upgrade to %i\n", | ||||
FEATURE_LATEST); | FEATURE_LATEST); | ||||
nMaxVersion = FEATURE_LATEST; | nMaxVersion = FEATURE_LATEST; | ||||
// permanently upgrade the wallet immediately | // permanently upgrade the wallet immediately | ||||
Show All 12 Lines | std::shared_ptr<CWallet> CWallet::CreateWalletFromFile( | ||||
} | } | ||||
// Upgrade to HD if explicit upgrade | // Upgrade to HD if explicit upgrade | ||||
if (gArgs.GetBoolArg("-upgradewallet", false)) { | if (gArgs.GetBoolArg("-upgradewallet", false)) { | ||||
LOCK(walletInstance->cs_wallet); | LOCK(walletInstance->cs_wallet); | ||||
// Do not upgrade versions to any version between HD_SPLIT and | // Do not upgrade versions to any version between HD_SPLIT and | ||||
// FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT | // FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT | ||||
int max_version = walletInstance->nWalletVersion; | int max_version = walletInstance->GetVersion(); | ||||
if (!walletInstance->CanSupportFeature(FEATURE_HD_SPLIT) && | if (!walletInstance->CanSupportFeature(FEATURE_HD_SPLIT) && | ||||
max_version >= FEATURE_HD_SPLIT && | max_version >= FEATURE_HD_SPLIT && | ||||
max_version < FEATURE_PRE_SPLIT_KEYPOOL) { | max_version < FEATURE_PRE_SPLIT_KEYPOOL) { | ||||
chain.initError( | chain.initError( | ||||
_("Cannot upgrade a non HD split wallet without upgrading to " | _("Cannot upgrade a non HD split wallet without upgrading to " | ||||
"support pre split keypool. Please use -upgradewallet=200300 " | "support pre split keypool. Please use -upgradewallet=200300 " | ||||
"or -upgradewallet with no version specified.") | "or -upgradewallet with no version specified.") | ||||
.translated); | .translated); | ||||
▲ Show 20 Lines • Show All 651 Lines • Show Last 20 Lines |