aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/interfaces/chain.cpp5
-rw-r--r--src/interfaces/chain.h6
-rw-r--r--src/test/interfaces_tests.cpp12
-rw-r--r--src/wallet/wallet.cpp11
4 files changed, 27 insertions, 7 deletions
diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp
index 8cd4ab0b6d..0d69c33be0 100644
--- a/src/interfaces/chain.cpp
+++ b/src/interfaces/chain.cpp
@@ -260,6 +260,11 @@ public:
WAIT_LOCK(cs_main, lock);
return FillBlock(LookupBlockIndex(hash), block, lock);
}
+ bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block) override
+ {
+ WAIT_LOCK(cs_main, lock);
+ return FillBlock(ChainActive().FindEarliestAtLeast(min_time, min_height), block, lock);
+ }
bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override
{
WAIT_LOCK(cs_main, lock);
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index ee79b3e6dc..16753b7cc1 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -146,6 +146,12 @@ public:
//! or contents.
virtual bool findBlock(const uint256& hash, const FoundBlock& block={}) = 0;
+ //! Find first block in the chain with timestamp >= the given time
+ //! and height >= than the given height, return false if there is no block
+ //! with a high enough timestamp and height. Optionally return block
+ //! information.
+ virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block={}) = 0;
+
//! Find ancestor of block at specified height and optionally return
//! ancestor information.
virtual bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out={}) = 0;
diff --git a/src/test/interfaces_tests.cpp b/src/test/interfaces_tests.cpp
index f95743ec40..b398b5819d 100644
--- a/src/test/interfaces_tests.cpp
+++ b/src/test/interfaces_tests.cpp
@@ -47,6 +47,18 @@ BOOST_AUTO_TEST_CASE(findBlock)
BOOST_CHECK(!chain->findBlock({}, FoundBlock()));
}
+BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
+{
+ auto chain = interfaces::MakeChain(m_node);
+ auto& active = ChainActive();
+ uint256 hash;
+ int height;
+ BOOST_CHECK(chain->findFirstBlockWithTimeAndHeight(/* min_time= */ 0, /* min_height= */ 5, FoundBlock().hash(hash).height(height)));
+ BOOST_CHECK_EQUAL(hash, active[5]->GetBlockHash());
+ BOOST_CHECK_EQUAL(height, 5);
+ BOOST_CHECK(!chain->findFirstBlockWithTimeAndHeight(/* min_time= */ active.Tip()->GetBlockTimeMax() + 1, /* min_height= */ 0));
+}
+
BOOST_AUTO_TEST_CASE(findAncestorByHeight)
{
auto chain = interfaces::MakeChain(m_node);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index c8641b03fb..9ffb810ee7 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -1591,15 +1591,12 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
// Find starting block. May be null if nCreateTime is greater than the
// highest blockchain timestamp, in which case there is nothing that needs
// to be scanned.
+ int start_height = 0;
uint256 start_block;
- {
- auto locked_chain = chain().lock();
- const Optional<int> start_height = locked_chain->findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, &start_block);
- const Optional<int> tip_height = locked_chain->getHeight();
- WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, tip_height && start_height ? *tip_height - *start_height + 1 : 0);
- }
+ bool start = chain().findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, FoundBlock().hash(start_block).height(start_height));
+ WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, start ? WITH_LOCK(cs_wallet, return GetLastBlockHeight()) - start_height + 1 : 0);
- if (!start_block.IsNull()) {
+ if (start) {
// TODO: this should take into account failure by ScanResult::USER_ABORT
ScanResult result = ScanForWalletTransactions(start_block, {} /* stop_block */, reserver, update);
if (result.status == ScanResult::FAILURE) {