Skip to content

Commit 3cb85ac

Browse files
committed
wallet refactor: Avoid use of Chain::Lock in CWallet::RescanFromTime
This is a step toward removing the Chain::Lock class and reducing cs_main locking. This change has no effect on behavior.
1 parent f7ba881 commit 3cb85ac

File tree

4 files changed

+27
-7
lines changed

4 files changed

+27
-7
lines changed

src/interfaces/chain.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,11 @@ class ChainImpl : public Chain
260260
WAIT_LOCK(cs_main, lock);
261261
return FillBlock(LookupBlockIndex(hash), block, lock);
262262
}
263+
bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
264+
{
265+
WAIT_LOCK(cs_main, lock);
266+
return FillBlock(ChainActive().FindEarliestAtLeast(min_time, min_height), block, lock);
267+
}
263268
bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override
264269
{
265270
WAIT_LOCK(cs_main, lock);

src/interfaces/chain.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ class Chain
146146
//! or contents.
147147
virtual bool findBlock(const uint256& hash, const FoundBlock& block={}) = 0;
148148

149+
//! Find first block in the chain with timestamp >= the given time
150+
//! and height >= than the given height, return false if there is no block
151+
//! with a high enough timestamp and height. Optionally return block
152+
//! information.
153+
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block={}) = 0;
154+
149155
//! Find ancestor of block at specified height and optionally return
150156
//! ancestor information.
151157
virtual bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out={}) = 0;

src/test/interfaces_tests.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,18 @@ BOOST_AUTO_TEST_CASE(findBlock)
4747
BOOST_CHECK(!chain->findBlock({}, FoundBlock()));
4848
}
4949

50+
BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
51+
{
52+
auto chain = interfaces::MakeChain(m_node);
53+
auto& active = ChainActive();
54+
uint256 hash;
55+
int height;
56+
BOOST_CHECK(chain->findFirstBlockWithTimeAndHeight(/* min_time= */ 0, /* min_height= */ 5, FoundBlock().hash(hash).height(height)));
57+
BOOST_CHECK_EQUAL(hash, active[5]->GetBlockHash());
58+
BOOST_CHECK_EQUAL(height, 5);
59+
BOOST_CHECK(!chain->findFirstBlockWithTimeAndHeight(/* min_time= */ active.Tip()->GetBlockTimeMax() + 1, /* min_height= */ 0));
60+
}
61+
5062
BOOST_AUTO_TEST_CASE(findAncestorByHeight)
5163
{
5264
auto chain = interfaces::MakeChain(m_node);

src/wallet/wallet.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1591,15 +1591,12 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
15911591
// Find starting block. May be null if nCreateTime is greater than the
15921592
// highest blockchain timestamp, in which case there is nothing that needs
15931593
// to be scanned.
1594+
int start_height = 0;
15941595
uint256 start_block;
1595-
{
1596-
auto locked_chain = chain().lock();
1597-
const Optional<int> start_height = locked_chain->findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, &start_block);
1598-
const Optional<int> tip_height = locked_chain->getHeight();
1599-
WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, tip_height && start_height ? *tip_height - *start_height + 1 : 0);
1600-
}
1596+
bool start = chain().findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, FoundBlock().hash(start_block).height(start_height));
1597+
WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, start ? WITH_LOCK(cs_wallet, return GetLastBlockHeight()) - start_height + 1 : 0);
16011598

1602-
if (!start_block.IsNull()) {
1599+
if (start) {
16031600
// TODO: this should take into account failure by ScanResult::USER_ABORT
16041601
ScanResult result = ScanForWalletTransactions(start_block, {} /* stop_block */, reserver, update);
16051602
if (result.status == ScanResult::FAILURE) {

0 commit comments

Comments
 (0)