Remove remaining chainActive references from CWallet

This commit does not change behavior.

Co-authored-by: Ben Woosley <ben.woosley@gmail.com>
pull/643/head
Russell Yanofsky 6 years ago
parent db21f02648
commit 44de1561aa

@ -60,6 +60,11 @@ class LockImpl : public Chain::Lock
assert(block != nullptr); assert(block != nullptr);
return block->GetMedianTimePast(); return block->GetMedianTimePast();
} }
bool haveBlockOnDisk(int height) override
{
CBlockIndex* block = ::chainActive[height];
return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
}
Optional<int> findFirstBlockWithTime(int64_t time, uint256* hash) override Optional<int> findFirstBlockWithTime(int64_t time, uint256* hash) override
{ {
CBlockIndex* block = ::chainActive.FindEarliestAtLeast(time); CBlockIndex* block = ::chainActive.FindEarliestAtLeast(time);
@ -112,6 +117,21 @@ class LockImpl : public Chain::Lock
} }
return nullopt; return nullopt;
} }
bool isPotentialTip(const uint256& hash) override
{
if (::chainActive.Tip()->GetBlockHash() == hash) return true;
CBlockIndex* block = LookupBlockIndex(hash);
return block && block->GetAncestor(::chainActive.Height()) == ::chainActive.Tip();
}
CBlockLocator getLocator() override { return ::chainActive.GetLocator(); }
Optional<int> findLocatorFork(const CBlockLocator& locator) override
{
LockAnnotation lock(::cs_main);
if (CBlockIndex* fork = FindForkInGlobalIndex(::chainActive, locator)) {
return fork->nHeight;
}
return nullopt;
}
}; };
class LockingStateImpl : public LockImpl, public UniqueLock<CCriticalSection> class LockingStateImpl : public LockImpl, public UniqueLock<CCriticalSection>

@ -15,6 +15,7 @@
class CBlock; class CBlock;
class CScheduler; class CScheduler;
class uint256; class uint256;
struct CBlockLocator;
namespace interfaces { namespace interfaces {
@ -58,6 +59,10 @@ public:
//! will abort. //! will abort.
virtual int64_t getBlockMedianTimePast(int height) = 0; virtual int64_t getBlockMedianTimePast(int height) = 0;
//! Check that the block is available on disk (i.e. has not been
//! pruned), and contains transactions.
virtual bool haveBlockOnDisk(int height) = 0;
//! Return height of the first block in the chain with timestamp equal //! Return height of the first block in the chain with timestamp equal
//! or greater than the given time, or nullopt if there is no block with //! or greater than the given time, or nullopt if there is no block with
//! a high enough timestamp. Also return the block hash as an optional //! a high enough timestamp. Also return the block hash as an optional
@ -84,6 +89,19 @@ public:
//! parameter (to avoid the cost of a second hash lookup in case this //! parameter (to avoid the cost of a second hash lookup in case this
//! information is desired). //! information is desired).
virtual Optional<int> findFork(const uint256& hash, Optional<int>* height) = 0; virtual Optional<int> findFork(const uint256& hash, Optional<int>* height) = 0;
//! Return true if block hash points to the current chain tip, or to a
//! possible descendant of the current chain tip that isn't currently
//! connected.
virtual bool isPotentialTip(const uint256& hash) = 0;
//! Get locator for the current chain tip.
virtual CBlockLocator getLocator() = 0;
//! Return height of the latest block common to locator and chain, which
//! is guaranteed to be an ancestor of the block used to create the
//! locator.
virtual Optional<int> findLocatorFork(const CBlockLocator& locator) = 0;
}; };
//! Return Lock interface. Chain is locked when this is called, and //! Return Lock interface. Chain is locked when this is called, and

@ -1166,7 +1166,7 @@ void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const
TransactionRemovedFromMempool(pblock->vtx[i]); TransactionRemovedFromMempool(pblock->vtx[i]);
} }
m_last_block_processed = pindex; m_last_block_processed = pindex->GetBlockHash();
} }
void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) { void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) {
@ -1191,9 +1191,8 @@ void CWallet::BlockUntilSyncedToCurrentChain() {
// protected by cs_wallet instead of cs_main, but as long as we need // protected by cs_wallet instead of cs_main, but as long as we need
// cs_main here anyway, it's easier to just call it cs_main-protected. // cs_main here anyway, it's easier to just call it cs_main-protected.
auto locked_chain = chain().lock(); auto locked_chain = chain().lock();
const CBlockIndex* initialChainTip = chainActive.Tip();
if (m_last_block_processed && m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) { if (!m_last_block_processed.IsNull() && locked_chain->isPotentialTip(m_last_block_processed)) {
return; return;
} }
} }
@ -4074,7 +4073,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
} }
auto locked_chain = chain.assumeLocked(); // Temporary. Removed in upcoming lock cleanup auto locked_chain = chain.assumeLocked(); // Temporary. Removed in upcoming lock cleanup
walletInstance->ChainStateFlushed(chainActive.GetLocator()); walletInstance->ChainStateFlushed(locked_chain->getLocator());
} else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) { } else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
// Make it impossible to disable private keys after creation // Make it impossible to disable private keys after creation
InitError(strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile)); InitError(strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile));
@ -4161,57 +4160,67 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
// 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();
LockAnnotation lock(::cs_main); // Temporary, for FindForkInGlobalIndex below. Removed in upcoming commit.
auto locked_chain = chain.lock(); auto locked_chain = chain.lock();
LOCK(walletInstance->cs_wallet); LOCK(walletInstance->cs_wallet);
CBlockIndex *pindexRescan = chainActive.Genesis(); int rescan_height = 0;
if (!gArgs.GetBoolArg("-rescan", false)) if (!gArgs.GetBoolArg("-rescan", false))
{ {
WalletBatch batch(*walletInstance->database); WalletBatch batch(*walletInstance->database);
CBlockLocator locator; CBlockLocator locator;
if (batch.ReadBestBlock(locator)) if (batch.ReadBestBlock(locator)) {
pindexRescan = FindForkInGlobalIndex(chainActive, locator); if (const Optional<int> fork_height = locked_chain->findLocatorFork(locator)) {
rescan_height = *fork_height;
}
}
} }
walletInstance->m_last_block_processed = chainActive.Tip(); const Optional<int> tip_height = locked_chain->getHeight();
if (tip_height) {
walletInstance->m_last_block_processed = locked_chain->getBlockHash(*tip_height);
} else {
walletInstance->m_last_block_processed.SetNull();
}
if (chainActive.Tip() && chainActive.Tip() != pindexRescan) if (tip_height && *tip_height != rescan_height)
{ {
//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 an old wallet within a pruned node //this might happen if a user uses an old wallet within a pruned node
// or if he ran -disablewallet for a longer time, then decided to re-enable // or if he ran -disablewallet for a longer time, then decided to re-enable
if (fPruneMode) if (fPruneMode)
{ {
CBlockIndex *block = chainActive.Tip(); int block_height = *tip_height;
while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block) while (block_height > 0 && locked_chain->haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
block = block->pprev; --block_height;
}
if (pindexRescan != block) { if (rescan_height != block_height) {
InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)")); InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"));
return nullptr; return nullptr;
} }
} }
uiInterface.InitMessage(_("Rescanning...")); uiInterface.InitMessage(_("Rescanning..."));
walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight); walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
// No need to read and scan block if block was created before // No need to read and scan block if block was created before
// our wallet birthday (as adjusted for block time variability) // our wallet birthday (as adjusted for block time variability)
while (pindexRescan && walletInstance->nTimeFirstKey && (pindexRescan->GetBlockTime() < (walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW))) { if (walletInstance->nTimeFirstKey) {
pindexRescan = chainActive.Next(pindexRescan); if (Optional<int> first_block = locked_chain->findFirstBlockWithTimeAndHeight(walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW, rescan_height)) {
rescan_height = *first_block;
}
} }
nStart = GetTimeMillis(); nStart = GetTimeMillis();
{ {
WalletRescanReserver reserver(walletInstance.get()); WalletRescanReserver reserver(walletInstance.get());
if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(pindexRescan->GetBlockHash(), {} /* stop block */, reserver, true /* update */).status)) { if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(locked_chain->getBlockHash(rescan_height), {} /* stop block */, reserver, true /* update */).status)) {
InitError(_("Failed to rescan the wallet during initialization")); InitError(_("Failed to rescan the wallet during initialization"));
return nullptr; return nullptr;
} }
} }
walletInstance->WalletLogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - nStart); walletInstance->WalletLogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - nStart);
walletInstance->ChainStateFlushed(chainActive.GetLocator()); walletInstance->ChainStateFlushed(locked_chain->getLocator());
walletInstance->database->IncrementUpdateCounter(); walletInstance->database->IncrementUpdateCounter();
// Restore wallet transaction metadata after -zapwallettxes=1 // Restore wallet transaction metadata after -zapwallettxes=1

@ -95,7 +95,6 @@ static const bool DEFAULT_DISABLE_WALLET = false;
//! Pre-calculated constants for input size estimation in *virtual size* //! Pre-calculated constants for input size estimation in *virtual size*
static constexpr size_t DUMMY_NESTED_P2WPKH_INPUT_SIZE = 91; static constexpr size_t DUMMY_NESTED_P2WPKH_INPUT_SIZE = 91;
class CBlockIndex;
class CCoinControl; class CCoinControl;
class COutput; class COutput;
class CReserveKey; class CReserveKey;
@ -723,10 +722,8 @@ private:
* Note that this is *not* how far we've processed, we may need some rescan * Note that this is *not* how far we've processed, we may need some rescan
* to have seen all transactions in the chain, but is only used to track * to have seen all transactions in the chain, but is only used to track
* live BlockConnected callbacks. * live BlockConnected callbacks.
*
* Protected by cs_main (see BlockUntilSyncedToCurrentChain)
*/ */
const CBlockIndex* m_last_block_processed = nullptr; uint256 m_last_block_processed;
public: public:
/* /*

Loading…
Cancel
Save