Changeset View
Changeset View
Standalone View
Standalone View
src/wallet/wallet.cpp
Show All 30 Lines | |||||
#include "validation.h" | #include "validation.h" | ||||
#include "wallet/coincontrol.h" | #include "wallet/coincontrol.h" | ||||
#include "wallet/fees.h" | #include "wallet/fees.h" | ||||
#include "wallet/finaltx.h" | #include "wallet/finaltx.h" | ||||
#include <boost/algorithm/string/replace.hpp> | #include <boost/algorithm/string/replace.hpp> | ||||
#include <cassert> | #include <cassert> | ||||
#include <future> | |||||
std::vector<CWalletRef> vpwallets; | std::vector<CWalletRef> vpwallets; | ||||
/** Transaction fee set by the user */ | /** Transaction fee set by the user */ | ||||
CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); | CFeeRate payTxFee(DEFAULT_TRANSACTION_FEE); | ||||
unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; | unsigned int nTxConfirmTarget = DEFAULT_TX_CONFIRM_TARGET; | ||||
bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE; | bool bSpendZeroConfChange = DEFAULT_SPEND_ZEROCONF_CHANGE; | ||||
▲ Show 20 Lines • Show All 1,235 Lines • ▼ Show 20 Lines | void CWallet::BlockConnected( | ||||
// that the conflicted transaction was evicted. | // that the conflicted transaction was evicted. | ||||
for (const CTransactionRef &ptx : vtxConflicted) { | for (const CTransactionRef &ptx : vtxConflicted) { | ||||
SyncTransaction(ptx); | SyncTransaction(ptx); | ||||
} | } | ||||
for (size_t i = 0; i < pblock->vtx.size(); i++) { | for (size_t i = 0; i < pblock->vtx.size(); i++) { | ||||
SyncTransaction(pblock->vtx[i], pindex, i); | SyncTransaction(pblock->vtx[i], pindex, i); | ||||
} | } | ||||
m_last_block_processed = pindex; | |||||
} | } | ||||
void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock> &pblock) { | void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock> &pblock) { | ||||
LOCK2(cs_main, cs_wallet); | LOCK2(cs_main, cs_wallet); | ||||
for (const CTransactionRef &ptx : pblock->vtx) { | for (const CTransactionRef &ptx : pblock->vtx) { | ||||
SyncTransaction(ptx); | SyncTransaction(ptx); | ||||
} | } | ||||
} | } | ||||
void CWallet::BlockUntilSyncedToCurrentChain() { | |||||
AssertLockNotHeld(cs_main); | |||||
AssertLockNotHeld(cs_wallet); | |||||
{ | |||||
// Skip the queue-draining stuff if we know we're caught up with | |||||
// chainActive.Tip()... | |||||
// We could also take cs_wallet here, and call m_last_block_processed | |||||
// protected by cs_wallet instead of cs_main, but as long as we need | |||||
// cs_main here anyway, its easier to just call it cs_main-protected. | |||||
LOCK(cs_main); | |||||
const CBlockIndex *initialChainTip = chainActive.Tip(); | |||||
if (m_last_block_processed->GetAncestor(initialChainTip->nHeight) == | |||||
initialChainTip) { | |||||
return; | |||||
} | |||||
} | |||||
// ...otherwise put a callback in the validation interface queue and wait | |||||
// for the queue to drain enough to execute it (indicating we are caught up | |||||
// at least with the time we entered this function). | |||||
std::promise<void> promise; | |||||
CallFunctionInValidationInterfaceQueue([&promise] { promise.set_value(); }); | |||||
promise.get_future().wait(); | |||||
} | |||||
isminetype CWallet::IsMine(const CTxIn &txin) const { | isminetype CWallet::IsMine(const CTxIn &txin) const { | ||||
LOCK(cs_wallet); | LOCK(cs_wallet); | ||||
std::map<TxId, CWalletTx>::const_iterator mi = | std::map<TxId, CWalletTx>::const_iterator mi = | ||||
mapWallet.find(txin.prevout.GetTxId()); | mapWallet.find(txin.prevout.GetTxId()); | ||||
if (mi != mapWallet.end()) { | if (mi != mapWallet.end()) { | ||||
const CWalletTx &prev = (*mi).second; | const CWalletTx &prev = (*mi).second; | ||||
if (txin.prevout.GetN() < prev.tx->vout.size()) { | if (txin.prevout.GetN() < prev.tx->vout.size()) { | ||||
return IsMine(prev.tx->vout[txin.prevout.GetN()]); | return IsMine(prev.tx->vout[txin.prevout.GetN()]); | ||||
▲ Show 20 Lines • Show All 2,774 Lines • ▼ Show 20 Lines | if (fFirstRun) { | ||||
"already existing non-HD wallet"), | "already existing non-HD wallet"), | ||||
walletFile)); | walletFile)); | ||||
return nullptr; | return nullptr; | ||||
} | } | ||||
} | } | ||||
LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); | LogPrintf(" wallet %15dms\n", GetTimeMillis() - nStart); | ||||
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)) { | ||||
CWalletDB walletdb(*walletInstance->dbw); | CWalletDB walletdb(*walletInstance->dbw); | ||||
CBlockLocator locator; | CBlockLocator locator; | ||||
if (walletdb.ReadBestBlock(locator)) { | if (walletdb.ReadBestBlock(locator)) { | ||||
pindexRescan = FindForkInGlobalIndex(chainActive, locator); | pindexRescan = FindForkInGlobalIndex(chainActive, locator); | ||||
} | } | ||||
} | } | ||||
walletInstance->m_last_block_processed = chainActive.Tip(); | |||||
RegisterValidationInterface(walletInstance); | |||||
if (chainActive.Tip() && chainActive.Tip() != pindexRescan) { | if (chainActive.Tip() && chainActive.Tip() != pindexRescan) { | ||||
// We can't rescan beyond non-pruned blocks, stop and throw an error. | // We can't rescan beyond non-pruned blocks, stop and throw an error. | ||||
// This might happen if a user uses a old wallet within a pruned node or | // This might happen if a user uses a old wallet within a pruned node or | ||||
// if he ran -disablewallet for a longer time, then decided to | // if he ran -disablewallet for a longer time, then decided to | ||||
// re-enable. | // re-enable. | ||||
if (fPruneMode) { | if (fPruneMode) { | ||||
CBlockIndex *block = chainActive.Tip(); | CBlockIndex *block = chainActive.Tip(); | ||||
while (block && block->pprev && block->pprev->nStatus.hasData() && | while (block && block->pprev && block->pprev->nStatus.hasData() && | ||||
▲ Show 20 Lines • Show All 155 Lines • Show Last 20 Lines |