Skip to content

Commit 7a87272

Browse files
ryanofskyEmpact
authored andcommitted
Remove remaining chainActive references from CWallet
1 parent 771101c commit 7a87272

File tree

4 files changed

+65
-23
lines changed

4 files changed

+65
-23
lines changed

src/interfaces/chain.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,11 @@ class LockImpl : public Chain::Lock
6161
assert(block != nullptr);
6262
return block->GetMedianTimePast();
6363
}
64+
bool haveBlockOnDisk(int height) override
65+
{
66+
CBlockIndex* block = ::chainActive[height];
67+
return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
68+
}
6469
Optional<int> findFirstBlockWithTime(int64_t time) override
6570
{
6671
CBlockIndex* block = ::chainActive.FindEarliestAtLeast(time);
@@ -111,6 +116,21 @@ class LockImpl : public Chain::Lock
111116
}
112117
return nullopt;
113118
}
119+
bool isPotentialTip(const uint256& hash) override
120+
{
121+
if (::chainActive.Tip()->GetBlockHash() == hash) return true;
122+
auto it = ::mapBlockIndex.find(hash);
123+
return it != ::mapBlockIndex.end() && it->second->GetAncestor(::chainActive.Height()) == ::chainActive.Tip();
124+
}
125+
CBlockLocator getLocator() override { return ::chainActive.GetLocator(); }
126+
Optional<int> findLocatorFork(const CBlockLocator& locator) override
127+
{
128+
LockAnnotation lock(::cs_main);
129+
if (CBlockIndex* fork = FindForkInGlobalIndex(::chainActive, locator)) {
130+
return fork->nHeight;
131+
}
132+
return nullopt;
133+
}
114134
};
115135

116136
class LockingStateImpl : public LockImpl, public UniqueLock<CCriticalSection>

src/interfaces/chain.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
class CBlock;
1616
class CScheduler;
1717
class uint256;
18+
struct CBlockLocator;
1819

1920
namespace interfaces {
2021

@@ -57,6 +58,10 @@ class Chain
5758
//! Get block median time past.
5859
virtual int64_t getBlockMedianTimePast(int height) = 0;
5960

61+
//! Check that the full block is available on disk (ie has not been
62+
//! pruned), and contains transactions.
63+
virtual bool haveBlockOnDisk(int height) = 0;
64+
6065
//! Return height of the first block in the chain with timestamp equal
6166
//! or greater than the given time, or nothing if there is no block with
6267
//! a high enough timestamp.
@@ -79,6 +84,17 @@ class Chain
7984
//! of the specified block. Also return the height of the specified
8085
//! block as an optional output parameter.
8186
virtual Optional<int> findFork(const uint256& hash, Optional<int>* height) = 0;
87+
88+
//! Return true if block hash points to the current chain tip, or to a
89+
//! possible descendant of the current chain tip that isn't currently
90+
//! connected.
91+
virtual bool isPotentialTip(const uint256& hash) = 0;
92+
93+
//! Get locator for the current chain tip.
94+
virtual CBlockLocator getLocator() = 0;
95+
96+
//! Return height of block on the chain using locator.
97+
virtual Optional<int> findLocatorFork(const CBlockLocator& locator) = 0;
8298
};
8399

84100
//! Return Lock interface. Chain is locked when this is called, and

src/wallet/wallet.cpp

Lines changed: 28 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,7 +1127,7 @@ void CWallet::BlockConnected(const std::shared_ptr<const CBlock>& pblock, const
11271127
TransactionRemovedFromMempool(pblock->vtx[i]);
11281128
}
11291129

1130-
m_last_block_processed = pindex;
1130+
m_last_block_processed = pindex->GetBlockHash();
11311131
}
11321132

11331133
void CWallet::BlockDisconnected(const std::shared_ptr<const CBlock>& pblock) {
@@ -1152,9 +1152,8 @@ void CWallet::BlockUntilSyncedToCurrentChain() {
11521152
// protected by cs_wallet instead of cs_main, but as long as we need
11531153
// cs_main here anyway, it's easier to just call it cs_main-protected.
11541154
auto locked_chain = chain().lock();
1155-
const CBlockIndex* initialChainTip = chainActive.Tip();
11561155

1157-
if (m_last_block_processed && m_last_block_processed->GetAncestor(initialChainTip->nHeight) == initialChainTip) {
1156+
if (!m_last_block_processed.IsNull() && locked_chain->isPotentialTip(m_last_block_processed)) {
11581157
return;
11591158
}
11601159
}
@@ -4010,7 +4009,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
40104009
}
40114010

40124011
auto locked_chain = chain.assumeLocked(); // Temporary. Removed in upcoming lock cleanup
4013-
walletInstance->ChainStateFlushed(chainActive.GetLocator());
4012+
walletInstance->ChainStateFlushed(locked_chain->getLocator());
40144013
} else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
40154014
// Make it impossible to disable private keys after creation
40164015
InitError(strprintf(_("Error loading %s: Private keys can only be disabled during creation"), walletFile));
@@ -4097,58 +4096,68 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
40974096
// Try to top up keypool. No-op if the wallet is locked.
40984097
walletInstance->TopUpKeyPool();
40994098

4100-
LockAnnotation lock(::cs_main); // Temporary, for FindForkInGlobalIndex below. Removed in upcoming commit.
41014099
auto locked_chain = chain.lock();
41024100
LOCK(walletInstance->cs_wallet);
41034101

4104-
CBlockIndex *pindexRescan = chainActive.Genesis();
4102+
int rescan_height = 0;
41054103
if (!gArgs.GetBoolArg("-rescan", false))
41064104
{
41074105
WalletBatch batch(*walletInstance->database);
41084106
CBlockLocator locator;
4109-
if (batch.ReadBestBlock(locator))
4110-
pindexRescan = FindForkInGlobalIndex(chainActive, locator);
4107+
if (batch.ReadBestBlock(locator)) {
4108+
if (const Optional<int> fork_height = locked_chain->findLocatorFork(locator)) {
4109+
rescan_height = *fork_height;
4110+
}
4111+
}
41114112
}
41124113

4113-
walletInstance->m_last_block_processed = chainActive.Tip();
4114+
const Optional<int> tip_height = locked_chain->getHeight();
4115+
if (tip_height) {
4116+
walletInstance->m_last_block_processed = locked_chain->getBlockHash(*tip_height);
4117+
} else {
4118+
walletInstance->m_last_block_processed.SetNull();
4119+
}
41144120

4115-
if (chainActive.Tip() && chainActive.Tip() != pindexRescan)
4121+
if (tip_height && *tip_height != rescan_height)
41164122
{
41174123
//We can't rescan beyond non-pruned blocks, stop and throw an error
41184124
//this might happen if a user uses an old wallet within a pruned node
41194125
// or if he ran -disablewallet for a longer time, then decided to re-enable
41204126
if (fPruneMode)
41214127
{
4122-
CBlockIndex *block = chainActive.Tip();
4123-
while (block && block->pprev && (block->pprev->nStatus & BLOCK_HAVE_DATA) && block->pprev->nTx > 0 && pindexRescan != block)
4124-
block = block->pprev;
4128+
int block_height = *tip_height;
4129+
while (block_height > 0 && locked_chain->haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
4130+
--block_height;
4131+
}
41254132

4126-
if (pindexRescan != block) {
4133+
if (rescan_height != block_height) {
41274134
InitError(_("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)"));
41284135
return nullptr;
41294136
}
41304137
}
41314138

41324139
uiInterface.InitMessage(_("Rescanning..."));
4133-
walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", chainActive.Height() - pindexRescan->nHeight, pindexRescan->nHeight);
4140+
walletInstance->WalletLogPrintf("Rescanning last %i blocks (from block %i)...\n", *tip_height - rescan_height, rescan_height);
41344141

41354142
// No need to read and scan block if block was created before
41364143
// our wallet birthday (as adjusted for block time variability)
4137-
while (pindexRescan && walletInstance->nTimeFirstKey && (pindexRescan->GetBlockTime() < (walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW))) {
4138-
pindexRescan = chainActive.Next(pindexRescan);
4144+
if (walletInstance->nTimeFirstKey) {
4145+
if (Optional<int> first_block = locked_chain->findFirstBlockWithTimeAndHeight(walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW, rescan_height)) {
4146+
rescan_height = *first_block;
4147+
}
41394148
}
41404149

41414150
nStart = GetTimeMillis();
41424151
{
41434152
WalletRescanReserver reserver(walletInstance.get());
41444153
uint256 stop_block, failed_block;
4145-
if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(pindexRescan->GetBlockHash(), {} /* stop block */, reserver, failed_block, stop_block, true /* update */))) {
4154+
if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(locked_chain->getBlockHash(rescan_height), {} /* stop block */, reserver, failed_block, stop_block, true /* update */))) {
41464155
InitError(_("Failed to rescan the wallet during initialization"));
41474156
return nullptr;
41484157
}
41494158
}
41504159
walletInstance->WalletLogPrintf("Rescan completed in %15dms\n", GetTimeMillis() - nStart);
4151-
walletInstance->ChainStateFlushed(chainActive.GetLocator());
4160+
walletInstance->ChainStateFlushed(locked_chain->getLocator());
41524161
walletInstance->database->IncrementUpdateCounter();
41534162

41544163
// Restore wallet transaction metadata after -zapwallettxes=1

src/wallet/wallet.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ static const bool DEFAULT_DISABLE_WALLET = false;
8888
//! Pre-calculated constants for input size estimation in *virtual size*
8989
static constexpr size_t DUMMY_NESTED_P2WPKH_INPUT_SIZE = 91;
9090

91-
class CBlockIndex;
9291
class CCoinControl;
9392
class COutput;
9493
class CReserveKey;
@@ -716,10 +715,8 @@ class CWallet final : public CCryptoKeyStore, public CValidationInterface
716715
* Note that this is *not* how far we've processed, we may need some rescan
717716
* to have seen all transactions in the chain, but is only used to track
718717
* live BlockConnected callbacks.
719-
*
720-
* Protected by cs_main (see BlockUntilSyncedToCurrentChain)
721718
*/
722-
const CBlockIndex* m_last_block_processed = nullptr;
719+
uint256 m_last_block_processed;
723720

724721
public:
725722
/*

0 commit comments

Comments
 (0)