aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces
diff options
context:
space:
mode:
authorRussell Yanofsky <russ@yanofsky.org>2020-01-21 17:08:12 -0500
committerRussell Yanofsky <russ@yanofsky.org>2020-03-31 08:36:02 -0500
commit1be8ff280c78c30baabae9429c53c0bebb89c44d (patch)
treee028b55f2c2821390f9e913be5d5fb1c3516f5a9 /src/interfaces
parent3cb85ac594f115db99f96b0a0f4bfdcd69ef0590 (diff)
downloadbitcoin-1be8ff280c78c30baabae9429c53c0bebb89c44d.tar.xz
wallet: Avoid use of Chain::Lock in rescanblockchain
This is a step toward removing the Chain::Lock class and reducing cs_main locking. This change only affects behavior in the case where wallet last block processed falls behind the chain tip. The rescanblockchain error height error checking will just be stricter in this case and only accept values up to the last processed height
Diffstat (limited to 'src/interfaces')
-rw-r--r--src/interfaces/chain.cpp33
-rw-r--r--src/interfaces/chain.h9
2 files changed, 24 insertions, 18 deletions
diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp
index 0d69c33be0..1c578b56ca 100644
--- a/src/interfaces/chain.cpp
+++ b/src/interfaces/chain.cpp
@@ -103,20 +103,6 @@ class LockImpl : public Chain::Lock, public UniqueLock<RecursiveMutex>
}
return nullopt;
}
- Optional<int> findPruned(int start_height, Optional<int> stop_height) override
- {
- LockAssertion lock(::cs_main);
- if (::fPruneMode) {
- CBlockIndex* block = stop_height ? ::ChainActive()[*stop_height] : ::ChainActive().Tip();
- while (block && block->nHeight >= start_height) {
- if ((block->nStatus & BLOCK_HAVE_DATA) == 0) {
- return block->nHeight;
- }
- block = block->pprev;
- }
- }
- return nullopt;
- }
Optional<int> findFork(const uint256& hash, Optional<int>* height) override
{
LockAssertion lock(::cs_main);
@@ -297,6 +283,25 @@ public:
LOCK(cs_main);
return GuessVerificationProgress(Params().TxData(), LookupBlockIndex(block_hash));
}
+ bool hasBlocks(const uint256& block_hash, int min_height, Optional<int> max_height) override
+ {
+ // hasBlocks returns true if all ancestors of block_hash in specified
+ // range have block data (are not pruned), false if any ancestors in
+ // specified range are missing data.
+ //
+ // For simplicity and robustness, min_height and max_height are only
+ // used to limit the range, and passing min_height that's too low or
+ // max_height that's too high will not crash or change the result.
+ LOCK(::cs_main);
+ if (CBlockIndex* block = LookupBlockIndex(block_hash)) {
+ if (max_height && block->nHeight >= *max_height) block = block->GetAncestor(*max_height);
+ for (; block->nStatus & BLOCK_HAVE_DATA; block = block->pprev) {
+ // Check pprev to not segfault if min_height is too low
+ if (block->nHeight <= min_height || !block->pprev) return true;
+ }
+ }
+ return false;
+ }
RBFTransactionState isRBFOptIn(const CTransaction& tx) override
{
LOCK(::mempool.cs);
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index 16753b7cc1..8bc0ed824c 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -114,10 +114,6 @@ public:
//! (to avoid the cost of a second lookup in case this information is needed.)
virtual Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) = 0;
- //! Return height of last block in the specified range which is pruned, or
- //! nullopt if no block in the range is pruned. Range is inclusive.
- virtual Optional<int> findPruned(int start_height = 0, Optional<int> stop_height = nullopt) = 0;
-
//! Return height of the specified block if it is on the chain, otherwise
//! return the height of the highest block on chain that's an ancestor
//! of the specified block, or nullopt if there is no common ancestor.
@@ -179,6 +175,11 @@ public:
//! the specified block hash are verified.
virtual double guessVerificationProgress(const uint256& block_hash) = 0;
+ //! Return true if data is available for all blocks in the specified range
+ //! of blocks. This checks all blocks that are ancestors of block_hash in
+ //! the height range from min_height to max_height, inclusive.
+ virtual bool hasBlocks(const uint256& block_hash, int min_height = 0, Optional<int> max_height = {}) = 0;
+
//! Check if transaction is RBF opt in.
virtual RBFTransactionState isRBFOptIn(const CTransaction& tx) = 0;