Skip to content

Commit 56376f3

Browse files
author
MarcoFalke
committed
Merge #15670: refactor: combine Chain::findFirstBlockWithTime/findFirstBlockWithTimeAndHeight
765c0b3 refactor: combine Chain::findFirstBlockWithTime/findFirstBlockWithTimeAndHeight (Antoine Riard) Pull request description: As suggested in #14711, pass height to CChain::FindEarliestAtLeast to simplify Chain interface by combining findFirstBlockWithTime and findFirstBlockWithTimeAndHeight into one ACKs for commit 765c0b: jnewbery: utACK 765c0b3. Nice work @ariard! ryanofsky: utACK 765c0b3. Looks good, thanks for implementing the suggestion! Tree-SHA512: 63f98252a93da95f08c0b6325ea98f717aa9ae4036d17eaa6edbec68e5ddd65672d66a6af267b80c36311fffa9b415a47308e95ea7718b300b685e23d4e9e6ec
2 parents b6a5583 + 765c0b3 commit 56376f3

File tree

7 files changed

+44
-54
lines changed

7 files changed

+44
-54
lines changed

src/chain.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,11 @@ const CBlockIndex *CChain::FindFork(const CBlockIndex *pindex) const {
5959
return pindex;
6060
}
6161

62-
CBlockIndex* CChain::FindEarliestAtLeast(int64_t nTime) const
62+
CBlockIndex* CChain::FindEarliestAtLeast(int64_t nTime, int height) const
6363
{
64-
std::vector<CBlockIndex*>::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), nTime,
65-
[](CBlockIndex* pBlock, const int64_t& time) -> bool { return pBlock->GetBlockTimeMax() < time; });
64+
std::pair<int64_t, int> blockparams = std::make_pair(nTime, height);
65+
std::vector<CBlockIndex*>::const_iterator lower = std::lower_bound(vChain.begin(), vChain.end(), blockparams,
66+
[](CBlockIndex* pBlock, const std::pair<int64_t, int>& blockparams) -> bool { return pBlock->GetBlockTimeMax() < blockparams.first || pBlock->nHeight < blockparams.second; });
6667
return (lower == vChain.end() ? nullptr : *lower);
6768
}
6869

src/chain.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -465,8 +465,8 @@ class CChain {
465465
/** Find the last common block between this chain and a block index entry. */
466466
const CBlockIndex *FindFork(const CBlockIndex *pindex) const;
467467

468-
/** Find the earliest block with timestamp equal or greater than the given. */
469-
CBlockIndex* FindEarliestAtLeast(int64_t nTime) const;
468+
/** Find the earliest block with timestamp equal or greater than the given time and height equal or greater than the given height. */
469+
CBlockIndex* FindEarliestAtLeast(int64_t nTime, int height) const;
470470
};
471471

472472
#endif // BITCOIN_CHAIN_H

src/interfaces/chain.cpp

Lines changed: 2 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -84,29 +84,15 @@ class LockImpl : public Chain::Lock
8484
CBlockIndex* block = ::chainActive[height];
8585
return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
8686
}
87-
Optional<int> findFirstBlockWithTime(int64_t time, uint256* hash) override
87+
Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) override
8888
{
89-
CBlockIndex* block = ::chainActive.FindEarliestAtLeast(time);
89+
CBlockIndex* block = ::chainActive.FindEarliestAtLeast(time, height);
9090
if (block) {
9191
if (hash) *hash = block->GetBlockHash();
9292
return block->nHeight;
9393
}
9494
return nullopt;
9595
}
96-
Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height) override
97-
{
98-
// TODO: Could update CChain::FindEarliestAtLeast() to take a height
99-
// parameter and use it with std::lower_bound() to make this
100-
// implementation more efficient and allow combining
101-
// findFirstBlockWithTime and findFirstBlockWithTimeAndHeight into one
102-
// method.
103-
for (CBlockIndex* block = ::chainActive[height]; block; block = ::chainActive.Next(block)) {
104-
if (block->GetBlockTime() >= time) {
105-
return block->nHeight;
106-
}
107-
}
108-
return nullopt;
109-
}
11096
Optional<int> findPruned(int start_height, Optional<int> stop_height) override
11197
{
11298
if (::fPruneMode) {

src/interfaces/chain.h

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -104,21 +104,12 @@ class Chain
104104
//! pruned), and contains transactions.
105105
virtual bool haveBlockOnDisk(int height) = 0;
106106

107-
//! Return height of the first block in the chain with timestamp equal
108-
//! or greater than the given time, or nullopt if there is no block with
109-
//! a high enough timestamp. Also return the block hash as an optional
110-
//! output parameter (to avoid the cost of a second lookup in case this
111-
//! information is needed.)
112-
virtual Optional<int> findFirstBlockWithTime(int64_t time, uint256* hash) = 0;
113-
114107
//! Return height of the first block in the chain with timestamp equal
115108
//! or greater than the given time and height equal or greater than the
116-
//! given height, or nullopt if there is no such block.
117-
//!
118-
//! Calling this with height 0 is equivalent to calling
119-
//! findFirstBlockWithTime, but less efficient because it requires a
120-
//! linear instead of a binary search.
121-
virtual Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height) = 0;
109+
//! given height, or nullopt if there is no block with a high enough
110+
//! timestamp and height. Also return the block hash as an optional output parameter
111+
//! (to avoid the cost of a second lookup in case this information is needed.)
112+
virtual Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) = 0;
122113

123114
//! Return height of last block in the specified range which is pruned, or
124115
//! nullopt if no block in the range is pruned. Range is inclusive.

src/rpc/blockchain.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1012,7 +1012,7 @@ static UniValue pruneblockchain(const JSONRPCRequest& request)
10121012
// too low to be a block time (corresponds to timestamp from Sep 2001).
10131013
if (heightParam > 1000000000) {
10141014
// Add a 2 hour buffer to include blocks which might have had old timestamps
1015-
CBlockIndex* pindex = chainActive.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW);
1015+
CBlockIndex* pindex = chainActive.FindEarliestAtLeast(heightParam - TIMESTAMP_WINDOW, 0);
10161016
if (!pindex) {
10171017
throw JSONRPCError(RPC_INVALID_PARAMETER, "Could not find block with at least the specified timestamp.");
10181018
}

src/test/skiplist_tests.cpp

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_test)
136136
// Pick a random element in vBlocksMain.
137137
int r = InsecureRandRange(vBlocksMain.size());
138138
int64_t test_time = vBlocksMain[r].nTime;
139-
CBlockIndex *ret = chain.FindEarliestAtLeast(test_time);
139+
CBlockIndex* ret = chain.FindEarliestAtLeast(test_time, 0);
140140
BOOST_CHECK(ret->nTimeMax >= test_time);
141141
BOOST_CHECK((ret->pprev==nullptr) || ret->pprev->nTimeMax < test_time);
142142
BOOST_CHECK(vBlocksMain[r].GetAncestor(ret->nHeight) == ret);
@@ -158,22 +158,34 @@ BOOST_AUTO_TEST_CASE(findearliestatleast_edge_test)
158158
CChain chain;
159159
chain.SetTip(&blocks.back());
160160

161-
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(50)->nHeight, 0);
162-
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(100)->nHeight, 0);
163-
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(150)->nHeight, 3);
164-
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(200)->nHeight, 3);
165-
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(250)->nHeight, 6);
166-
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(300)->nHeight, 6);
167-
BOOST_CHECK(!chain.FindEarliestAtLeast(350));
168-
169-
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0)->nHeight, 0);
170-
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-1)->nHeight, 0);
171-
172-
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::min())->nHeight, 0);
173-
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-int64_t(std::numeric_limits<unsigned int>::max()) - 1)->nHeight, 0);
174-
BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::max()));
175-
BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::max()));
176-
BOOST_CHECK(!chain.FindEarliestAtLeast(int64_t(std::numeric_limits<unsigned int>::max()) + 1));
161+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(50, 0)->nHeight, 0);
162+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(100, 0)->nHeight, 0);
163+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(150, 0)->nHeight, 3);
164+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(200, 0)->nHeight, 3);
165+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(250, 0)->nHeight, 6);
166+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(300, 0)->nHeight, 6);
167+
BOOST_CHECK(!chain.FindEarliestAtLeast(350, 0));
168+
169+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 0)->nHeight, 0);
170+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-1, 0)->nHeight, 0);
171+
172+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::min(), 0)->nHeight, 0);
173+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(-int64_t(std::numeric_limits<unsigned int>::max()) - 1, 0)->nHeight, 0);
174+
BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<int64_t>::max(), 0));
175+
BOOST_CHECK(!chain.FindEarliestAtLeast(std::numeric_limits<unsigned int>::max(), 0));
176+
BOOST_CHECK(!chain.FindEarliestAtLeast(int64_t(std::numeric_limits<unsigned int>::max()) + 1, 0));
177+
178+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, -1)->nHeight, 0);
179+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 0)->nHeight, 0);
180+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 3)->nHeight, 3);
181+
BOOST_CHECK_EQUAL(chain.FindEarliestAtLeast(0, 8)->nHeight, 8);
182+
BOOST_CHECK(!chain.FindEarliestAtLeast(0, 9));
183+
184+
CBlockIndex* ret1 = chain.FindEarliestAtLeast(100, 2);
185+
BOOST_CHECK(ret1->nTimeMax >= 100 && ret1->nHeight == 2);
186+
BOOST_CHECK(!chain.FindEarliestAtLeast(300, 9));
187+
CBlockIndex* ret2 = chain.FindEarliestAtLeast(200, 4);
188+
BOOST_CHECK(ret2->nTimeMax >= 200 && ret2->nHeight == 4);
177189
}
178190

179191
BOOST_AUTO_TEST_SUITE_END()

src/wallet/wallet.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1728,7 +1728,7 @@ int64_t CWallet::RescanFromTime(int64_t startTime, const WalletRescanReserver& r
17281728
uint256 start_block;
17291729
{
17301730
auto locked_chain = chain().lock();
1731-
const Optional<int> start_height = locked_chain->findFirstBlockWithTime(startTime - TIMESTAMP_WINDOW, &start_block);
1731+
const Optional<int> start_height = locked_chain->findFirstBlockWithTimeAndHeight(startTime - TIMESTAMP_WINDOW, 0, &start_block);
17321732
const Optional<int> tip_height = locked_chain->getHeight();
17331733
WalletLogPrintf("%s: Rescanning last %i blocks\n", __func__, tip_height && start_height ? *tip_height - *start_height + 1 : 0);
17341734
}
@@ -4257,7 +4257,7 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
42574257
// No need to read and scan block if block was created before
42584258
// our wallet birthday (as adjusted for block time variability)
42594259
if (walletInstance->nTimeFirstKey) {
4260-
if (Optional<int> first_block = locked_chain->findFirstBlockWithTimeAndHeight(walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW, rescan_height)) {
4260+
if (Optional<int> first_block = locked_chain->findFirstBlockWithTimeAndHeight(walletInstance->nTimeFirstKey - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
42614261
rescan_height = *first_block;
42624262
}
42634263
}

0 commit comments

Comments
 (0)