Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show First 20 Lines • Show All 331 Lines • ▼ Show 20 Lines | |||||
bool CWallet::LoadCScript(const CScript &redeemScript) { | bool CWallet::LoadCScript(const CScript &redeemScript) { | ||||
/** | /** | ||||
* A sanity check was added in pull #3843 to avoid adding redeemScripts that | * A sanity check was added in pull #3843 to avoid adding redeemScripts that | ||||
* never can be redeemed. However, old wallets may still contain these. Do | * never can be redeemed. However, old wallets may still contain these. Do | ||||
* not add them to the wallet and warn. | * not add them to the wallet and warn. | ||||
*/ | */ | ||||
if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) { | if (redeemScript.size() > MAX_SCRIPT_ELEMENT_SIZE) { | ||||
std::string strAddr = EncodeDestination(CScriptID(redeemScript)); | std::string strAddr = EncodeDestination(CScriptID(redeemScript)); | ||||
LogPrintf("%s: Warning: This wallet contains a redeemScript of size %i " | LogPrint(BCLog::WALLET, | ||||
"%s: Warning: This wallet contains a redeemScript of size %i " | |||||
"which exceeds maximum size %i thus can never be redeemed. " | "which exceeds maximum size %i thus can never be redeemed. " | ||||
"Do not use address %s.\n", | "Do not use address %s.\n", | ||||
__func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, | __func__, redeemScript.size(), MAX_SCRIPT_ELEMENT_SIZE, | ||||
strAddr); | strAddr); | ||||
return true; | return true; | ||||
} | } | ||||
return CCryptoKeyStore::AddCScript(redeemScript); | return CCryptoKeyStore::AddCScript(redeemScript); | ||||
} | } | ||||
bool CWallet::AddWatchOnly(const CScript &dest) { | bool CWallet::AddWatchOnly(const CScript &dest) { | ||||
if (!CCryptoKeyStore::AddWatchOnly(dest)) { | if (!CCryptoKeyStore::AddWatchOnly(dest)) { | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | for (MasterKeyMap::value_type &pMasterKey : mapMasterKeys) { | ||||
pMasterKey.second.nDeriveIterations * 100 / | pMasterKey.second.nDeriveIterations * 100 / | ||||
double(GetTimeMillis() - nStartTime)) / | double(GetTimeMillis() - nStartTime)) / | ||||
2; | 2; | ||||
if (pMasterKey.second.nDeriveIterations < 25000) { | if (pMasterKey.second.nDeriveIterations < 25000) { | ||||
pMasterKey.second.nDeriveIterations = 25000; | pMasterKey.second.nDeriveIterations = 25000; | ||||
} | } | ||||
LogPrintf( | LogPrint( | ||||
BCLog::WALLET, | |||||
"Wallet passphrase changed to an nDeriveIterations of %i\n", | "Wallet passphrase changed to an nDeriveIterations of %i\n", | ||||
pMasterKey.second.nDeriveIterations); | pMasterKey.second.nDeriveIterations); | ||||
if (!crypter.SetKeyFromPassphrase( | if (!crypter.SetKeyFromPassphrase( | ||||
strNewWalletPassphrase, pMasterKey.second.vchSalt, | strNewWalletPassphrase, pMasterKey.second.vchSalt, | ||||
pMasterKey.second.nDeriveIterations, | pMasterKey.second.nDeriveIterations, | ||||
pMasterKey.second.nDerivationMethod)) { | pMasterKey.second.nDerivationMethod)) { | ||||
return false; | return false; | ||||
▲ Show 20 Lines • Show All 221 Lines • ▼ Show 20 Lines | kMasterKey.nDeriveIterations = | ||||
kMasterKey.nDeriveIterations * 100 / | kMasterKey.nDeriveIterations * 100 / | ||||
((double)(GetTimeMillis() - nStartTime))) / | ((double)(GetTimeMillis() - nStartTime))) / | ||||
2; | 2; | ||||
if (kMasterKey.nDeriveIterations < 25000) { | if (kMasterKey.nDeriveIterations < 25000) { | ||||
kMasterKey.nDeriveIterations = 25000; | kMasterKey.nDeriveIterations = 25000; | ||||
} | } | ||||
LogPrintf("Encrypting Wallet with an nDeriveIterations of %i\n", | LogPrint(BCLog::WALLET, | ||||
"Encrypting Wallet with an nDeriveIterations of %i\n", | |||||
kMasterKey.nDeriveIterations); | kMasterKey.nDeriveIterations); | ||||
if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, | if (!crypter.SetKeyFromPassphrase(strWalletPassphrase, kMasterKey.vchSalt, | ||||
kMasterKey.nDeriveIterations, | kMasterKey.nDeriveIterations, | ||||
kMasterKey.nDerivationMethod)) { | kMasterKey.nDerivationMethod)) { | ||||
return false; | return false; | ||||
} | } | ||||
if (!crypter.Encrypt(_vMasterKey, kMasterKey.vchCryptedKey)) { | if (!crypter.Encrypt(_vMasterKey, kMasterKey.vchCryptedKey)) { | ||||
▲ Show 20 Lines • Show All 272 Lines • ▼ Show 20 Lines | if (!fInsertedNew) { | ||||
if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe) { | if (wtxIn.fFromMe && wtxIn.fFromMe != wtx.fFromMe) { | ||||
wtx.fFromMe = wtxIn.fFromMe; | wtx.fFromMe = wtxIn.fFromMe; | ||||
fUpdated = true; | fUpdated = true; | ||||
} | } | ||||
} | } | ||||
//// debug print | //// debug print | ||||
LogPrintf("AddToWallet %s %s%s\n", wtxIn.GetId().ToString(), | LogPrint(BCLog::WALLET, "AddToWallet %s %s%s\n", wtxIn.GetId().ToString(), | ||||
(fInsertedNew ? "new" : ""), (fUpdated ? "update" : "")); | (fInsertedNew ? "new" : ""), (fUpdated ? "update" : "")); | ||||
// Write to disk | // Write to disk | ||||
if ((fInsertedNew || fUpdated) && !walletdb.WriteTx(wtx)) { | if ((fInsertedNew || fUpdated) && !walletdb.WriteTx(wtx)) { | ||||
return false; | return false; | ||||
} | } | ||||
// Break debit/credit balance caches: | // Break debit/credit balance caches: | ||||
wtx.MarkDirty(); | wtx.MarkDirty(); | ||||
▲ Show 20 Lines • Show All 55 Lines • ▼ Show 20 Lines | bool CWallet::AddToWalletIfInvolvingMe(const CTransactionRef &ptx, | ||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
if (pIndex != nullptr) { | if (pIndex != nullptr) { | ||||
for (const CTxIn &txin : tx.vin) { | for (const CTxIn &txin : tx.vin) { | ||||
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> | std::pair<TxSpends::const_iterator, TxSpends::const_iterator> | ||||
range = mapTxSpends.equal_range(txin.prevout); | range = mapTxSpends.equal_range(txin.prevout); | ||||
while (range.first != range.second) { | while (range.first != range.second) { | ||||
if (range.first->second != tx.GetId()) { | if (range.first->second != tx.GetId()) { | ||||
LogPrintf("Transaction %s (in block %s) conflicts with " | LogPrint(BCLog::WALLET, | ||||
"Transaction %s (in block %s) conflicts with " | |||||
"wallet transaction %s (both spend %s:%i)\n", | "wallet transaction %s (both spend %s:%i)\n", | ||||
tx.GetId().ToString(), | tx.GetId().ToString(), | ||||
pIndex->GetBlockHash().ToString(), | pIndex->GetBlockHash().ToString(), | ||||
range.first->second.ToString(), | range.first->second.ToString(), | ||||
range.first->first.GetTxId().ToString(), | range.first->first.GetTxId().ToString(), | ||||
range.first->first.GetN()); | range.first->first.GetN()); | ||||
MarkConflicted(pIndex->GetBlockHash(), range.first->second); | MarkConflicted(pIndex->GetBlockHash(), range.first->second); | ||||
} | } | ||||
range.first++; | range.first++; | ||||
} | } | ||||
} | } | ||||
} | } | ||||
bool fExisted = mapWallet.count(tx.GetId()) != 0; | bool fExisted = mapWallet.count(tx.GetId()) != 0; | ||||
Show All 14 Lines | if (fExisted || IsMine(tx) || IsFromMe(tx)) { | ||||
// extract addresses and check if they match with an unused keypool | // extract addresses and check if they match with an unused keypool | ||||
// key | // key | ||||
std::vector<CKeyID> vAffected; | std::vector<CKeyID> vAffected; | ||||
CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey); | CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey); | ||||
for (const CKeyID &keyid : vAffected) { | for (const CKeyID &keyid : vAffected) { | ||||
std::map<CKeyID, int64_t>::const_iterator mi = | std::map<CKeyID, int64_t>::const_iterator mi = | ||||
m_pool_key_to_index.find(keyid); | m_pool_key_to_index.find(keyid); | ||||
if (mi != m_pool_key_to_index.end()) { | if (mi != m_pool_key_to_index.end()) { | ||||
LogPrintf("%s: Detected a used keypool key, mark all " | LogPrint(BCLog::WALLET, | ||||
"%s: Detected a used keypool key, mark all " | |||||
"keypool key up to this key as used\n", | "keypool key up to this key as used\n", | ||||
__func__); | __func__); | ||||
MarkReserveKeysAsUsed(mi->second); | MarkReserveKeysAsUsed(mi->second); | ||||
if (!TopUpKeyPool()) { | if (!TopUpKeyPool()) { | ||||
LogPrintf( | LogPrint( | ||||
BCLog::WALLET, | |||||
"%s: Topping up keypool failed (locked wallet)\n", | "%s: Topping up keypool failed (locked wallet)\n", | ||||
__func__); | __func__); | ||||
} | } | ||||
} | } | ||||
} | } | ||||
} | } | ||||
CWalletTx wtx(this, ptx); | CWalletTx wtx(this, ptx); | ||||
▲ Show 20 Lines • Show All 485 Lines • ▼ Show 20 Lines | for (unsigned int i = 0; i < tx->vout.size(); ++i) { | ||||
continue; | continue; | ||||
} | } | ||||
// In either case, we need to get the destination address. | // In either case, we need to get the destination address. | ||||
CTxDestination address; | CTxDestination address; | ||||
if (!ExtractDestination(txout.scriptPubKey, address) && | if (!ExtractDestination(txout.scriptPubKey, address) && | ||||
!txout.scriptPubKey.IsUnspendable()) { | !txout.scriptPubKey.IsUnspendable()) { | ||||
LogPrintf("CWalletTx::GetAmounts: Unknown transaction type found, " | LogPrint(BCLog::WALLET, | ||||
"CWalletTx::GetAmounts: Unknown transaction type found, " | |||||
"txid %s\n", | "txid %s\n", | ||||
this->GetId().ToString()); | this->GetId().ToString()); | ||||
address = CNoDestination(); | address = CNoDestination(); | ||||
} | } | ||||
COutputEntry output = {address, txout.nValue, (int)i}; | COutputEntry output = {address, txout.nValue, (int)i}; | ||||
// If we are debited by the transaction, add the output as a "sent" | // If we are debited by the transaction, add the output as a "sent" | ||||
// entry. | // entry. | ||||
if (nDebit > Amount::zero()) { | if (nDebit > Amount::zero()) { | ||||
Show All 19 Lines | int64_t CWallet::RescanFromTime(int64_t startTime, bool update) { | ||||
AssertLockHeld(cs_main); | AssertLockHeld(cs_main); | ||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
// Find starting block. May be null if nCreateTime is greater than the | // Find starting block. May be null if nCreateTime is greater than the | ||||
// highest blockchain timestamp, in which case there is nothing that needs | // highest blockchain timestamp, in which case there is nothing that needs | ||||
// to be scanned. | // to be scanned. | ||||
CBlockIndex *const startBlock = | CBlockIndex *const startBlock = | ||||
chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW); | chainActive.FindEarliestAtLeast(startTime - TIMESTAMP_WINDOW); | ||||
LogPrintf("%s: Rescanning last %i blocks\n", __func__, | LogPrint(BCLog::WALLET, "%s: Rescanning last %i blocks\n", __func__, | ||||
startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0); | startBlock ? chainActive.Height() - startBlock->nHeight + 1 : 0); | ||||
if (startBlock) { | if (startBlock) { | ||||
const CBlockIndex *const failedBlock = | const CBlockIndex *const failedBlock = | ||||
ScanForWalletTransactions(startBlock, nullptr, update); | ScanForWalletTransactions(startBlock, nullptr, update); | ||||
if (failedBlock) { | if (failedBlock) { | ||||
return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1; | return failedBlock->GetBlockTimeMax() + TIMESTAMP_WINDOW + 1; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | while (pindex && !fAbortRescan) { | ||||
} | } | ||||
if (pindex == pindexStop) { | if (pindex == pindexStop) { | ||||
break; | break; | ||||
} | } | ||||
pindex = chainActive.Next(pindex); | pindex = chainActive.Next(pindex); | ||||
if (GetTime() >= nNow + 60) { | if (GetTime() >= nNow + 60) { | ||||
nNow = GetTime(); | nNow = GetTime(); | ||||
LogPrintf("Still rescanning. At block %d. Progress=%f\n", | LogPrint(BCLog::WALLET, | ||||
"Still rescanning. At block %d. Progress=%f\n", | |||||
pindex->nHeight, | pindex->nHeight, | ||||
GuessVerificationProgress(chainParams.TxData(), pindex)); | GuessVerificationProgress(chainParams.TxData(), pindex)); | ||||
} | } | ||||
} | } | ||||
if (pindex && fAbortRescan) { | if (pindex && fAbortRescan) { | ||||
LogPrintf("Rescan aborted at block %d. Progress=%f\n", pindex->nHeight, | LogPrint(BCLog::WALLET, "Rescan aborted at block %d. Progress=%f\n", | ||||
pindex->nHeight, | |||||
GuessVerificationProgress(chainParams.TxData(), pindex)); | GuessVerificationProgress(chainParams.TxData(), pindex)); | ||||
} | } | ||||
// Hide progress dialog in GUI. | // Hide progress dialog in GUI. | ||||
ShowProgress(_("Rescanning..."), 100); | ShowProgress(_("Rescanning..."), 100); | ||||
fScanningWallet = false; | fScanningWallet = false; | ||||
return ret; | return ret; | ||||
} | } | ||||
Show All 36 Lines | bool CWalletTx::RelayWalletTransaction(CConnman *connman) { | ||||
assert(pwallet->GetBroadcastTransactions()); | assert(pwallet->GetBroadcastTransactions()); | ||||
if (IsCoinBase() || isAbandoned() || GetDepthInMainChain() != 0) { | if (IsCoinBase() || isAbandoned() || GetDepthInMainChain() != 0) { | ||||
return false; | return false; | ||||
} | } | ||||
CValidationState state; | CValidationState state; | ||||
// GetDepthInMainChain already catches known conflicts. | // GetDepthInMainChain already catches known conflicts. | ||||
if (InMempool() || AcceptToMemoryPool(maxTxFee, state)) { | if (InMempool() || AcceptToMemoryPool(maxTxFee, state)) { | ||||
LogPrintf("Relaying wtx %s\n", GetId().ToString()); | LogPrint(BCLog::WALLET, "Relaying wtx %s\n", GetId().ToString()); | ||||
if (connman) { | if (connman) { | ||||
CInv inv(MSG_TX, GetId()); | CInv inv(MSG_TX, GetId()); | ||||
connman->ForEachNode( | connman->ForEachNode( | ||||
[&inv](CNode *pnode) { pnode->PushInventory(inv); }); | [&inv](CNode *pnode) { pnode->PushInventory(inv); }); | ||||
return true; | return true; | ||||
} | } | ||||
} | } | ||||
▲ Show 20 Lines • Show All 290 Lines • ▼ Show 20 Lines | void CWallet::ResendWalletTransactions(int64_t nBestBlockTime, | ||||
nLastResend = GetTime(); | nLastResend = GetTime(); | ||||
// Rebroadcast unconfirmed txes older than 5 minutes before the last block | // Rebroadcast unconfirmed txes older than 5 minutes before the last block | ||||
// was found: | // was found: | ||||
std::vector<uint256> relayed = | std::vector<uint256> relayed = | ||||
ResendWalletTransactionsBefore(nBestBlockTime - 5 * 60, connman); | ResendWalletTransactionsBefore(nBestBlockTime - 5 * 60, connman); | ||||
if (!relayed.empty()) { | if (!relayed.empty()) { | ||||
LogPrintf("%s: rebroadcast %u unconfirmed transactions\n", __func__, | LogPrint(BCLog::WALLET, "%s: rebroadcast %u unconfirmed transactions\n", | ||||
relayed.size()); | __func__, relayed.size()); | ||||
} | } | ||||
} | } | ||||
/** @} */ // end of mapWallet | /** @} */ // end of mapWallet | ||||
/** | /** | ||||
* @defgroup Actions | * @defgroup Actions | ||||
* | * | ||||
▲ Show 20 Lines • Show All 974 Lines • ▼ Show 20 Lines | |||||
} | } | ||||
/** | /** | ||||
* Call after CreateTransaction unless you want to abort | * Call after CreateTransaction unless you want to abort | ||||
*/ | */ | ||||
bool CWallet::CommitTransaction(CWalletTx &wtxNew, CReserveKey &reservekey, | bool CWallet::CommitTransaction(CWalletTx &wtxNew, CReserveKey &reservekey, | ||||
CConnman *connman, CValidationState &state) { | CConnman *connman, CValidationState &state) { | ||||
LOCK2(cs_main, cs_wallet); | LOCK2(cs_main, cs_wallet); | ||||
LogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString()); | LogPrint(BCLog::WALLET, "CommitTransaction:\n%s", wtxNew.tx->ToString()); | ||||
// Take key pair from key pool so it won't be used again. | // Take key pair from key pool so it won't be used again. | ||||
reservekey.KeepKey(); | reservekey.KeepKey(); | ||||
// Add tx to wallet, because if it has change it's also ours, otherwise just | // Add tx to wallet, because if it has change it's also ours, otherwise just | ||||
// for transaction history. | // for transaction history. | ||||
AddToWallet(wtxNew); | AddToWallet(wtxNew); | ||||
// Notify that old coins are spent. | // Notify that old coins are spent. | ||||
for (const CTxIn &txin : wtxNew.tx->vin) { | for (const CTxIn &txin : wtxNew.tx->vin) { | ||||
CWalletTx &coin = mapWallet[txin.prevout.GetTxId()]; | CWalletTx &coin = mapWallet[txin.prevout.GetTxId()]; | ||||
coin.BindWallet(this); | coin.BindWallet(this); | ||||
NotifyTransactionChanged(this, coin.GetId(), CT_UPDATED); | NotifyTransactionChanged(this, coin.GetId(), CT_UPDATED); | ||||
} | } | ||||
// Track how many getdata requests our transaction gets. | // Track how many getdata requests our transaction gets. | ||||
mapRequestCount[wtxNew.GetId()] = 0; | mapRequestCount[wtxNew.GetId()] = 0; | ||||
if (fBroadcastTransactions) { | if (fBroadcastTransactions) { | ||||
// Broadcast | // Broadcast | ||||
if (!wtxNew.AcceptToMemoryPool(maxTxFee, state)) { | if (!wtxNew.AcceptToMemoryPool(maxTxFee, state)) { | ||||
LogPrintf("CommitTransaction(): Transaction cannot be " | LogPrint(BCLog::WALLET, | ||||
"CommitTransaction(): Transaction cannot be " | |||||
"broadcast immediately, %s\n", | "broadcast immediately, %s\n", | ||||
state.GetRejectReason()); | state.GetRejectReason()); | ||||
// TODO: if we expect the failure to be long term or permanent, | // TODO: if we expect the failure to be long term or permanent, | ||||
// instead delete wtx from the wallet and return failure. | // instead delete wtx from the wallet and return failure. | ||||
} else { | } else { | ||||
wtxNew.RelayWalletTransaction(connman); | wtxNew.RelayWalletTransaction(connman); | ||||
} | } | ||||
} | } | ||||
return true; | return true; | ||||
▲ Show 20 Lines • Show All 186 Lines • ▼ Show 20 Lines | bool CWallet::NewKeyPool() { | ||||
setExternalKeyPool.clear(); | setExternalKeyPool.clear(); | ||||
m_pool_key_to_index.clear(); | m_pool_key_to_index.clear(); | ||||
if (!TopUpKeyPool()) { | if (!TopUpKeyPool()) { | ||||
return false; | return false; | ||||
} | } | ||||
LogPrintf("CWallet::NewKeyPool rewrote keypool\n"); | LogPrint(BCLog::WALLET, "CWallet::NewKeyPool rewrote keypool\n"); | ||||
return true; | return true; | ||||
} | } | ||||
size_t CWallet::KeypoolCountExternalKeys() { | size_t CWallet::KeypoolCountExternalKeys() { | ||||
// setExternalKeyPool | // setExternalKeyPool | ||||
AssertLockHeld(cs_wallet); | AssertLockHeld(cs_wallet); | ||||
return setExternalKeyPool.size(); | return setExternalKeyPool.size(); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Lines | for (int64_t i = missingInternal + missingExternal; i--;) { | ||||
if (internal) { | if (internal) { | ||||
setInternalKeyPool.insert(index); | setInternalKeyPool.insert(index); | ||||
} else { | } else { | ||||
setExternalKeyPool.insert(index); | setExternalKeyPool.insert(index); | ||||
} | } | ||||
m_pool_key_to_index[pubkey.GetID()] = index; | m_pool_key_to_index[pubkey.GetID()] = index; | ||||
} | } | ||||
if (missingInternal + missingExternal > 0) { | if (missingInternal + missingExternal > 0) { | ||||
LogPrintf( | LogPrint(BCLog::WALLET, | ||||
"keypool added %d keys (%d internal), size=%u (%u internal)\n", | "keypool added %d keys (%d internal), size=%u (%u internal)\n", | ||||
missingInternal + missingExternal, missingInternal, | missingInternal + missingExternal, missingInternal, | ||||
setInternalKeyPool.size() + setExternalKeyPool.size(), | setInternalKeyPool.size() + setExternalKeyPool.size(), | ||||
setInternalKeyPool.size()); | setInternalKeyPool.size()); | ||||
} | } | ||||
return true; | return true; | ||||
} | } | ||||
void CWallet::ReserveKeyFromKeyPool(int64_t &nIndex, CKeyPool &keypool, | void CWallet::ReserveKeyFromKeyPool(int64_t &nIndex, CKeyPool &keypool, | ||||
bool fRequestedInternal) { | bool fRequestedInternal) { | ||||
nIndex = -1; | nIndex = -1; | ||||
Show All 30 Lines | void CWallet::ReserveKeyFromKeyPool(int64_t &nIndex, CKeyPool &keypool, | ||||
} | } | ||||
if (keypool.fInternal != fReturningInternal) { | if (keypool.fInternal != fReturningInternal) { | ||||
throw std::runtime_error(std::string(__func__) + | throw std::runtime_error(std::string(__func__) + | ||||
": keypool entry misclassified"); | ": keypool entry misclassified"); | ||||
} | } | ||||
assert(keypool.vchPubKey.IsValid()); | assert(keypool.vchPubKey.IsValid()); | ||||
m_pool_key_to_index.erase(keypool.vchPubKey.GetID()); | m_pool_key_to_index.erase(keypool.vchPubKey.GetID()); | ||||
LogPrintf("keypool reserve %d\n", nIndex); | LogPrint(BCLog::WALLET, "keypool reserve %d\n", nIndex); | ||||
} | } | ||||
void CWallet::KeepKey(int64_t nIndex) { | void CWallet::KeepKey(int64_t nIndex) { | ||||
// Remove from key pool. | // Remove from key pool. | ||||
CWalletDB walletdb(*dbw); | CWalletDB walletdb(*dbw); | ||||
walletdb.ErasePool(nIndex); | walletdb.ErasePool(nIndex); | ||||
LogPrintf("keypool keep %d\n", nIndex); | LogPrint(BCLog::WALLET, "keypool keep %d\n", nIndex); | ||||
} | } | ||||
void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey &pubkey) { | void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey &pubkey) { | ||||
// Return to key pool | // Return to key pool | ||||
{ | { | ||||
LOCK(cs_wallet); | LOCK(cs_wallet); | ||||
if (fInternal) { | if (fInternal) { | ||||
setInternalKeyPool.insert(nIndex); | setInternalKeyPool.insert(nIndex); | ||||
} else { | } else { | ||||
setExternalKeyPool.insert(nIndex); | setExternalKeyPool.insert(nIndex); | ||||
} | } | ||||
m_pool_key_to_index[pubkey.GetID()] = nIndex; | m_pool_key_to_index[pubkey.GetID()] = nIndex; | ||||
} | } | ||||
LogPrintf("keypool return %d\n", nIndex); | LogPrint(BCLog::WALLET, "keypool return %d\n", nIndex); | ||||
} | } | ||||
bool CWallet::GetKeyFromPool(CPubKey &result, bool internal) { | bool CWallet::GetKeyFromPool(CPubKey &result, bool internal) { | ||||
CKeyPool keypool; | CKeyPool keypool; | ||||
LOCK(cs_wallet); | LOCK(cs_wallet); | ||||
int64_t nIndex = 0; | int64_t nIndex = 0; | ||||
ReserveKeyFromKeyPool(nIndex, keypool, internal); | ReserveKeyFromKeyPool(nIndex, keypool, internal); | ||||
if (nIndex == -1) { | if (nIndex == -1) { | ||||
▲ Show 20 Lines • Show All 445 Lines • ▼ Show 20 Lines | if (!wtx.hashUnset()) { | ||||
} | } | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
int64_t blocktime = mapBlockIndex[wtx.hashBlock]->GetBlockTime(); | int64_t blocktime = mapBlockIndex[wtx.hashBlock]->GetBlockTime(); | ||||
nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); | nTimeSmart = std::max(latestEntry, std::min(blocktime, latestNow)); | ||||
} else { | } else { | ||||
LogPrintf("%s: found %s in block %s not in index\n", __func__, | LogPrint(BCLog::WALLET, "%s: found %s in block %s not in index\n", | ||||
wtx.GetId().ToString(), wtx.hashBlock.ToString()); | __func__, wtx.GetId().ToString(), | ||||
wtx.hashBlock.ToString()); | |||||
} | } | ||||
} | } | ||||
return nTimeSmart; | return nTimeSmart; | ||||
} | } | ||||
bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, | bool CWallet::AddDestData(const CTxDestination &dest, const std::string &key, | ||||
const std::string &value) { | const std::string &value) { | ||||
if (boost::get<CNoDestination>(&dest)) { | if (boost::get<CNoDestination>(&dest)) { | ||||
▲ Show 20 Lines • Show All 96 Lines • ▼ Show 20 Lines | if (nLoadWalletRet != DB_LOAD_OK) { | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
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); | LogPrint(BCLog::WALLET, "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); | ||||
} else { | } else { | ||||
LogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion); | LogPrint(BCLog::WALLET, "Allowing wallet upgrade up to %i\n", | ||||
nMaxVersion); | |||||
} | } | ||||
if (nMaxVersion < walletInstance->GetVersion()) { | if (nMaxVersion < walletInstance->GetVersion()) { | ||||
InitError(_("Cannot downgrade wallet")); | InitError(_("Cannot downgrade wallet")); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
walletInstance->SetMaxVersion(nMaxVersion); | walletInstance->SetMaxVersion(nMaxVersion); | ||||
Show All 35 Lines | if (fFirstRun) { | ||||
if (!walletInstance->IsHDEnabled() && useHD) { | if (!walletInstance->IsHDEnabled() && useHD) { | ||||
InitError(strprintf(_("Error loading %s: You can't enable HD on a " | InitError(strprintf(_("Error loading %s: You can't enable HD on a " | ||||
"already existing non-HD wallet"), | "already existing non-HD wallet"), | ||||
walletFile)); | walletFile)); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); | LogPrint(BCLog::WALLET, " wallet %15dms\n", GetTimeMillis() - nStart); | ||||
RegisterValidationInterface(walletInstance); | RegisterValidationInterface(walletInstance); | ||||
// Try to top up keypool. No-op if the wallet is locked. | // Try to top up keypool. No-op if the wallet is locked. | ||||
walletInstance->TopUpKeyPool(); | walletInstance->TopUpKeyPool(); | ||||
CBlockIndex *pindexRescan = chainActive.Genesis(); | CBlockIndex *pindexRescan = chainActive.Genesis(); | ||||
if (!gArgs.GetBoolArg("-rescan", false)) { | if (!gArgs.GetBoolArg("-rescan", false)) { | ||||
Show All 20 Lines | if (chainActive.Tip() && chainActive.Tip() != pindexRescan) { | ||||
InitError(_("Prune: last wallet synchronisation goes beyond " | InitError(_("Prune: last wallet synchronisation goes beyond " | ||||
"pruned data. You need to -reindex (download the " | "pruned data. You need to -reindex (download the " | ||||
"whole blockchain again in case of pruned node)")); | "whole blockchain again in case of pruned node)")); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
uiInterface.InitMessage(_("Rescanning...")); | uiInterface.InitMessage(_("Rescanning...")); | ||||
LogPrintf("Rescanning last %i blocks (from block %i)...\n", | LogPrint(BCLog::WALLET, | ||||
"Rescanning last %i blocks (from block %i)...\n", | |||||
chainActive.Height() - pindexRescan->nHeight, | chainActive.Height() - pindexRescan->nHeight, | ||||
pindexRescan->nHeight); | pindexRescan->nHeight); | ||||
// No need to read and scan block if block was created before our wallet | // No need to read and scan block if block was created before our wallet | ||||
// birthday (as adjusted for block time variability) | // birthday (as adjusted for block time variability) | ||||
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(); | ||||
walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, true); | walletInstance->ScanForWalletTransactions(pindexRescan, nullptr, true); | ||||
LogPrintf(" rescan %15dms\n", GetTimeMillis() - nStart); | LogPrint(BCLog::WALLET, " rescan %15dms\n", | ||||
GetTimeMillis() - nStart); | |||||
walletInstance->SetBestChain(chainActive.GetLocator()); | walletInstance->SetBestChain(chainActive.GetLocator()); | ||||
walletInstance->dbw->IncrementUpdateCounter(); | walletInstance->dbw->IncrementUpdateCounter(); | ||||
// Restore wallet transaction metadata after -zapwallettxes=1 | // Restore wallet transaction metadata after -zapwallettxes=1 | ||||
if (gArgs.GetBoolArg("-zapwallettxes", false) && | if (gArgs.GetBoolArg("-zapwallettxes", false) && | ||||
gArgs.GetArg("-zapwallettxes", "1") != "2") { | gArgs.GetArg("-zapwallettxes", "1") != "2") { | ||||
CWalletDB walletdb(*walletInstance->dbw); | CWalletDB walletdb(*walletInstance->dbw); | ||||
Show All 16 Lines | if (chainActive.Tip() && chainActive.Tip() != pindexRescan) { | ||||
} | } | ||||
} | } | ||||
} | } | ||||
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()); | LogPrint(BCLog::WALLET, "setKeyPool.size() = %u\n", | ||||
LogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size()); | walletInstance->GetKeyPoolSize()); | ||||
LogPrintf("mapAddressBook.size() = %u\n", | LogPrint(BCLog::WALLET, "mapWallet.size() = %u\n", | ||||
walletInstance->mapWallet.size()); | |||||
LogPrint(BCLog::WALLET, "mapAddressBook.size() = %u\n", | |||||
walletInstance->mapAddressBook.size()); | walletInstance->mapAddressBook.size()); | ||||
return walletInstance; | return walletInstance; | ||||
} | } | ||||
std::atomic<bool> CWallet::fFlushScheduled(false); | std::atomic<bool> CWallet::fFlushScheduled(false); | ||||
void CWallet::postInitProcess(CScheduler &scheduler) { | void CWallet::postInitProcess(CScheduler &scheduler) { | ||||
// Add wallet transactions that aren't already in a block to mempool. | // Add wallet transactions that aren't already in a block to mempool. | ||||
▲ Show 20 Lines • Show All 83 Lines • Show Last 20 Lines |