aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcoFalke <falke.marco@gmail.com>2020-12-08 18:47:38 +0100
committerMarcoFalke <falke.marco@gmail.com>2020-12-08 18:49:02 +0100
commite98d1d674091681f88c5872f3e3923e37ce81b00 (patch)
treec916a17f54393e2292e9583e84e94d6193221bd2
parent16b31cc4c516cdcaf6d2eb2dd1255cc3e6973ba1 (diff)
parent5baa88fd38c8efa0e361636bb2c60af89d27b5d5 (diff)
downloadbitcoin-e98d1d674091681f88c5872f3e3923e37ce81b00.tar.xz
Merge #19425: refactor: Get rid of more redundant chain methods
5baa88fd38c8efa0e361636bb2c60af89d27b5d5 test: Remove no longer needed MakeChain calls (Russell Yanofsky) 6965f1352d2d7086d308750ce83a84f191a17755 refactor: Replace uses ChainActive() in interfaces/chain.cpp (Russell Yanofsky) 3fbbb9a6403a86fbed3d5d9f7939998922593377 refactor: Get rid of more redundant chain methods (Russell Yanofsky) Pull request description: This just drops three interfaces::Chain methods replacing them with other calls. Motivation for removing these chain methods: - Need to get rid of findFirstBlockWithTimeAndHeight for #10102, which doesn't support overloaded methods - Followup from https://github.com/bitcoin/bitcoin/pull/16426#discussion_r412487403 - phantomcircuit comments about findNextBlock test http://www.erisian.com.au/bitcoin-core-dev/log-2020-06-06.html#l-214 Behavior is not changing in any way here. A TODO comment in ScanForWalletTransactions was removed, but just because it was invalid (see https://github.com/bitcoin/bitcoin/pull/19195#discussion_r448020762), not because it was implemented. ACKs for top commit: MarcoFalke: re-ACK 5baa88fd38c8efa0e361636bb2c60af89d27b5d5 🕶 dongcarl: ACK 5baa88fd38c8efa0e361636bb2c60af89d27b5d5 Tree-SHA512: d20a2a8cf8742e6100c6d3a4871ed67f184925712cf9e55d301abee60353bf3f74cd0d46a13be1715d1c2faef72102bb321654d08a128c2ef6880f72b72a6687
-rw-r--r--src/bench/wallet_balance.cpp6
-rw-r--r--src/interfaces/chain.h29
-rw-r--r--src/node/interfaces.cpp65
-rw-r--r--src/test/interfaces_tests.cpp51
-rw-r--r--src/wallet/test/coinselector_tests.cpp2
-rw-r--r--src/wallet/test/init_test_fixture.cpp2
-rw-r--r--src/wallet/test/init_test_fixture.h1
-rw-r--r--src/wallet/test/ismine_tests.cpp3
-rw-r--r--src/wallet/test/scriptpubkeyman_tests.cpp4
-rw-r--r--src/wallet/test/wallet_test_fixture.cpp4
-rw-r--r--src/wallet/test/wallet_test_fixture.h3
-rw-r--r--src/wallet/test/wallet_tests.cpp49
-rw-r--r--src/wallet/wallet.cpp32
13 files changed, 101 insertions, 150 deletions
diff --git a/src/bench/wallet_balance.cpp b/src/bench/wallet_balance.cpp
index b3b73284d8..aa436ee3ea 100644
--- a/src/bench/wallet_balance.cpp
+++ b/src/bench/wallet_balance.cpp
@@ -24,15 +24,13 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
const auto& ADDRESS_WATCHONLY = ADDRESS_BCRT1_UNSPENDABLE;
- NodeContext node;
- std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
- CWallet wallet{chain.get(), "", CreateMockWalletDatabase()};
+ CWallet wallet{test_setup.m_node.chain.get(), "", CreateMockWalletDatabase()};
{
wallet.SetupLegacyScriptPubKeyMan();
bool first_run;
if (wallet.LoadWallet(first_run) != DBErrors::LOAD_OK) assert(false);
}
- auto handler = chain->handleNotifications({&wallet, [](CWallet*) {}});
+ auto handler = test_setup.m_node.chain->handleNotifications({&wallet, [](CWallet*) {}});
const Optional<std::string> address_mine{add_mine ? Optional<std::string>{getnewaddress(wallet)} : nullopt};
if (add_watchonly) importaddress(wallet, ADDRESS_WATCHONLY);
diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
index 85d09be0f3..1a49518d69 100644
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -44,6 +44,10 @@ public:
FoundBlock& time(int64_t& time) { m_time = &time; return *this; }
FoundBlock& maxTime(int64_t& max_time) { m_max_time = &max_time; return *this; }
FoundBlock& mtpTime(int64_t& mtp_time) { m_mtp_time = &mtp_time; return *this; }
+ //! Return whether block is in the active (most-work) chain.
+ FoundBlock& inActiveChain(bool& in_active_chain) { m_in_active_chain = &in_active_chain; return *this; }
+ //! Return next block in the active chain if current block is in the active chain.
+ FoundBlock& nextBlock(const FoundBlock& next_block) { m_next_block = &next_block; return *this; }
//! Read block data from disk. If the block exists but doesn't have data
//! (for example due to pruning), the CBlock variable will be set to null.
FoundBlock& data(CBlock& data) { m_data = &data; return *this; }
@@ -53,6 +57,8 @@ public:
int64_t* m_time = nullptr;
int64_t* m_max_time = nullptr;
int64_t* m_mtp_time = nullptr;
+ bool* m_in_active_chain = nullptr;
+ const FoundBlock* m_next_block = nullptr;
CBlock* m_data = nullptr;
};
@@ -77,9 +83,9 @@ public:
//! wallet cache it, fee estimation being driven by node mempool, wallet
//! should be the consumer.
//!
-//! * The `guessVerificationProgress`, `getBlockHeight`, `getBlockHash`, etc
-//! methods can go away if rescan logic is moved on the node side, and wallet
-//! only register rescan request.
+//! * `guessVerificationProgress` and similar methods can go away if rescan
+//! logic moves out of the wallet, and the wallet just requests scans from the
+//! node (https://github.com/bitcoin/bitcoin/issues/11756)
class Chain
{
public:
@@ -90,11 +96,6 @@ public:
//! any blocks)
virtual Optional<int> getHeight() = 0;
- //! Get block height above genesis block. Returns 0 for genesis block,
- //! 1 for following block, and so on. Returns nullopt for a block not
- //! included in the current chain.
- virtual Optional<int> getBlockHeight(const uint256& hash) = 0;
-
//! Get block hash. Height must be valid or this function will abort.
virtual uint256 getBlockHash(int height) = 0;
@@ -102,13 +103,6 @@ public:
//! pruned), and contains transactions.
virtual bool haveBlockOnDisk(int height) = 0;
- //! Return height of the first block in the chain with timestamp equal
- //! or greater than the given time and height equal or greater than the
- //! given height, or nullopt if there is no block with a high enough
- //! timestamp and height. Also return the block hash as an optional output parameter
- //! (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;
-
//! Get locator for the current chain tip.
virtual CBlockLocator getTipLocator() = 0;
@@ -130,11 +124,6 @@ public:
//! information.
virtual bool findFirstBlockWithTimeAndHeight(int64_t min_time, int min_height, const FoundBlock& block={}) = 0;
- //! Find next block if block is part of current chain. Also flag if
- //! there was a reorg and the specified block hash is no longer in the
- //! current chain, and optionally return block information.
- virtual bool findNextBlock(const uint256& block_hash, int block_height, const FoundBlock& next={}, bool* reorg=nullptr) = 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/node/interfaces.cpp b/src/node/interfaces.cpp
index da3e759e38..a872067b82 100644
--- a/src/node/interfaces.cpp
+++ b/src/node/interfaces.cpp
@@ -303,7 +303,7 @@ public:
util::Ref m_context_ref;
};
-bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock)
+bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<RecursiveMutex>& lock, const CChain& active)
{
if (!index) return false;
if (block.m_hash) *block.m_hash = index->GetBlockHash();
@@ -311,6 +311,8 @@ bool FillBlock(const CBlockIndex* index, const FoundBlock& block, UniqueLock<Rec
if (block.m_time) *block.m_time = index->GetBlockTime();
if (block.m_max_time) *block.m_max_time = index->GetBlockTimeMax();
if (block.m_mtp_time) *block.m_mtp_time = index->GetMedianTimePast();
+ if (block.m_in_active_chain) *block.m_in_active_chain = active[index->nHeight] == index;
+ if (block.m_next_block) FillBlock(active[index->nHeight] == index ? active[index->nHeight + 1] : nullptr, *block.m_next_block, lock, active);
if (block.m_data) {
REVERSE_LOCK(lock);
if (!ReadBlockFromDisk(*block.m_data, index, Params().GetConsensus())) block.m_data->SetNull();
@@ -413,48 +415,33 @@ public:
Optional<int> getHeight() override
{
LOCK(::cs_main);
- int height = ::ChainActive().Height();
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ int height = active.Height();
if (height >= 0) {
return height;
}
return nullopt;
}
- Optional<int> getBlockHeight(const uint256& hash) override
- {
- LOCK(::cs_main);
- CBlockIndex* block = LookupBlockIndex(hash);
- if (block && ::ChainActive().Contains(block)) {
- return block->nHeight;
- }
- return nullopt;
- }
uint256 getBlockHash(int height) override
{
LOCK(::cs_main);
- CBlockIndex* block = ::ChainActive()[height];
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ CBlockIndex* block = active[height];
assert(block);
return block->GetBlockHash();
}
bool haveBlockOnDisk(int height) override
{
LOCK(cs_main);
- CBlockIndex* block = ::ChainActive()[height];
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ CBlockIndex* block = active[height];
return block && ((block->nStatus & BLOCK_HAVE_DATA) != 0) && block->nTx > 0;
}
- Optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) override
- {
- LOCK(cs_main);
- CBlockIndex* block = ::ChainActive().FindEarliestAtLeast(time, height);
- if (block) {
- if (hash) *hash = block->GetBlockHash();
- return block->nHeight;
- }
- return nullopt;
- }
CBlockLocator getTipLocator() override
{
LOCK(cs_main);
- return ::ChainActive().GetLocator();
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ return active.GetLocator();
}
bool checkFinalTx(const CTransaction& tx) override
{
@@ -464,7 +451,8 @@ public:
Optional<int> findLocatorFork(const CBlockLocator& locator) override
{
LOCK(cs_main);
- if (CBlockIndex* fork = FindForkInGlobalIndex(::ChainActive(), locator)) {
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ if (CBlockIndex* fork = FindForkInGlobalIndex(active, locator)) {
return fork->nHeight;
}
return nullopt;
@@ -472,47 +460,45 @@ public:
bool findBlock(const uint256& hash, const FoundBlock& block) override
{
WAIT_LOCK(cs_main, lock);
- return FillBlock(LookupBlockIndex(hash), block, lock);
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ return FillBlock(LookupBlockIndex(hash), block, lock, active);
}
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 findNextBlock(const uint256& block_hash, int block_height, const FoundBlock& next, bool* reorg) override {
- WAIT_LOCK(cs_main, lock);
- CBlockIndex* block = ChainActive()[block_height];
- if (block && block->GetBlockHash() != block_hash) block = nullptr;
- if (reorg) *reorg = !block;
- return FillBlock(block ? ChainActive()[block_height + 1] : nullptr, next, lock);
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ return FillBlock(active.FindEarliestAtLeast(min_time, min_height), block, lock, active);
}
bool findAncestorByHeight(const uint256& block_hash, int ancestor_height, const FoundBlock& ancestor_out) override
{
WAIT_LOCK(cs_main, lock);
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
if (const CBlockIndex* block = LookupBlockIndex(block_hash)) {
if (const CBlockIndex* ancestor = block->GetAncestor(ancestor_height)) {
- return FillBlock(ancestor, ancestor_out, lock);
+ return FillBlock(ancestor, ancestor_out, lock, active);
}
}
- return FillBlock(nullptr, ancestor_out, lock);
+ return FillBlock(nullptr, ancestor_out, lock, active);
}
bool findAncestorByHash(const uint256& block_hash, const uint256& ancestor_hash, const FoundBlock& ancestor_out) override
{
WAIT_LOCK(cs_main, lock);
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
const CBlockIndex* block = LookupBlockIndex(block_hash);
const CBlockIndex* ancestor = LookupBlockIndex(ancestor_hash);
if (block && ancestor && block->GetAncestor(ancestor->nHeight) != ancestor) ancestor = nullptr;
- return FillBlock(ancestor, ancestor_out, lock);
+ return FillBlock(ancestor, ancestor_out, lock, active);
}
bool findCommonAncestor(const uint256& block_hash1, const uint256& block_hash2, const FoundBlock& ancestor_out, const FoundBlock& block1_out, const FoundBlock& block2_out) override
{
WAIT_LOCK(cs_main, lock);
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
const CBlockIndex* block1 = LookupBlockIndex(block_hash1);
const CBlockIndex* block2 = LookupBlockIndex(block_hash2);
const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
// Using & instead of && below to avoid short circuiting and leaving
// output uninitialized.
- return FillBlock(ancestor, ancestor_out, lock) & FillBlock(block1, block1_out, lock) & FillBlock(block2, block2_out, lock);
+ return FillBlock(ancestor, ancestor_out, lock, active) & FillBlock(block1, block1_out, lock, active) & FillBlock(block2, block2_out, lock, active);
}
void findCoins(std::map<COutPoint, Coin>& coins) override { return FindCoins(m_node, coins); }
double guessVerificationProgress(const uint256& block_hash) override
@@ -632,7 +618,8 @@ public:
{
if (!old_tip.IsNull()) {
LOCK(::cs_main);
- if (old_tip == ::ChainActive().Tip()->GetBlockHash()) return;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
+ if (old_tip == active.Tip()->GetBlockHash()) return;
}
SyncWithValidationInterfaceQueue();
}
diff --git a/src/test/interfaces_tests.cpp b/src/test/interfaces_tests.cpp
index b0d4de89f3..73463b071e 100644
--- a/src/test/interfaces_tests.cpp
+++ b/src/test/interfaces_tests.cpp
@@ -17,8 +17,8 @@ BOOST_FIXTURE_TEST_SUITE(interfaces_tests, TestChain100Setup)
BOOST_AUTO_TEST_CASE(findBlock)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
uint256 hash;
BOOST_CHECK(chain->findBlock(active[10]->GetBlockHash(), FoundBlock().hash(hash)));
@@ -44,13 +44,25 @@ BOOST_AUTO_TEST_CASE(findBlock)
BOOST_CHECK(chain->findBlock(active[60]->GetBlockHash(), FoundBlock().mtpTime(mtp_time)));
BOOST_CHECK_EQUAL(mtp_time, active[60]->GetMedianTimePast());
+ bool cur_active{false}, next_active{false};
+ uint256 next_hash;
+ BOOST_CHECK_EQUAL(active.Height(), 100);
+ BOOST_CHECK(chain->findBlock(active[99]->GetBlockHash(), FoundBlock().inActiveChain(cur_active).nextBlock(FoundBlock().inActiveChain(next_active).hash(next_hash))));
+ BOOST_CHECK(cur_active);
+ BOOST_CHECK(next_active);
+ BOOST_CHECK_EQUAL(next_hash, active[100]->GetBlockHash());
+ cur_active = next_active = false;
+ BOOST_CHECK(chain->findBlock(active[100]->GetBlockHash(), FoundBlock().inActiveChain(cur_active).nextBlock(FoundBlock().inActiveChain(next_active))));
+ BOOST_CHECK(cur_active);
+ BOOST_CHECK(!next_active);
+
BOOST_CHECK(!chain->findBlock({}, FoundBlock()));
}
BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
uint256 hash;
int height;
BOOST_CHECK(chain->findFirstBlockWithTimeAndHeight(/* min_time= */ 0, /* min_height= */ 5, FoundBlock().hash(hash).height(height)));
@@ -59,25 +71,10 @@ BOOST_AUTO_TEST_CASE(findFirstBlockWithTimeAndHeight)
BOOST_CHECK(!chain->findFirstBlockWithTimeAndHeight(/* min_time= */ active.Tip()->GetBlockTimeMax() + 1, /* min_height= */ 0));
}
-BOOST_AUTO_TEST_CASE(findNextBlock)
-{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
- bool reorg;
- uint256 hash;
- BOOST_CHECK(chain->findNextBlock(active[20]->GetBlockHash(), 20, FoundBlock().hash(hash), &reorg));
- BOOST_CHECK_EQUAL(hash, active[21]->GetBlockHash());
- BOOST_CHECK_EQUAL(reorg, false);
- BOOST_CHECK(!chain->findNextBlock(uint256(), 20, {}, &reorg));
- BOOST_CHECK_EQUAL(reorg, true);
- BOOST_CHECK(!chain->findNextBlock(active.Tip()->GetBlockHash(), active.Height(), {}, &reorg));
- BOOST_CHECK_EQUAL(reorg, false);
-}
-
BOOST_AUTO_TEST_CASE(findAncestorByHeight)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
uint256 hash;
BOOST_CHECK(chain->findAncestorByHeight(active[20]->GetBlockHash(), 10, FoundBlock().hash(hash)));
BOOST_CHECK_EQUAL(hash, active[10]->GetBlockHash());
@@ -86,8 +83,8 @@ BOOST_AUTO_TEST_CASE(findAncestorByHeight)
BOOST_AUTO_TEST_CASE(findAncestorByHash)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
int height = -1;
BOOST_CHECK(chain->findAncestorByHash(active[20]->GetBlockHash(), active[10]->GetBlockHash(), FoundBlock().height(height)));
BOOST_CHECK_EQUAL(height, 10);
@@ -96,8 +93,8 @@ BOOST_AUTO_TEST_CASE(findAncestorByHash)
BOOST_AUTO_TEST_CASE(findCommonAncestor)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
auto* orig_tip = active.Tip();
for (int i = 0; i < 10; ++i) {
BlockValidationState state;
@@ -126,8 +123,8 @@ BOOST_AUTO_TEST_CASE(findCommonAncestor)
BOOST_AUTO_TEST_CASE(hasBlocks)
{
- auto chain = interfaces::MakeChain(m_node);
- auto& active = ChainActive();
+ auto& chain = m_node.chain;
+ const CChain& active = Assert(m_node.chainman)->ActiveChain();
// Test ranges
BOOST_CHECK(chain->hasBlocks(active.Tip()->GetBlockHash(), 10, 90));
diff --git a/src/wallet/test/coinselector_tests.cpp b/src/wallet/test/coinselector_tests.cpp
index f38ccba384..4127cd45f8 100644
--- a/src/wallet/test/coinselector_tests.cpp
+++ b/src/wallet/test/coinselector_tests.cpp
@@ -283,7 +283,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
// Make sure that can use BnB when there are preset inputs
empty_wallet();
{
- std::unique_ptr<CWallet> wallet = MakeUnique<CWallet>(m_chain.get(), "", CreateMockWalletDatabase());
+ std::unique_ptr<CWallet> wallet = MakeUnique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->SetupLegacyScriptPubKeyMan();
diff --git a/src/wallet/test/init_test_fixture.cpp b/src/wallet/test/init_test_fixture.cpp
index c80310045a..334e4ae0d8 100644
--- a/src/wallet/test/init_test_fixture.cpp
+++ b/src/wallet/test/init_test_fixture.cpp
@@ -10,7 +10,7 @@
InitWalletDirTestingSetup::InitWalletDirTestingSetup(const std::string& chainName) : BasicTestingSetup(chainName)
{
- m_wallet_client = MakeWalletClient(*m_chain, *Assert(m_node.args));
+ m_wallet_client = MakeWalletClient(*m_node.chain, *Assert(m_node.args));
std::string sep;
sep += fs::path::preferred_separator;
diff --git a/src/wallet/test/init_test_fixture.h b/src/wallet/test/init_test_fixture.h
index f5bade77df..f666c45a34 100644
--- a/src/wallet/test/init_test_fixture.h
+++ b/src/wallet/test/init_test_fixture.h
@@ -19,7 +19,6 @@ struct InitWalletDirTestingSetup: public BasicTestingSetup {
fs::path m_datadir;
fs::path m_cwd;
std::map<std::string, fs::path> m_walletdir_path_cases;
- std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
std::unique_ptr<interfaces::WalletClient> m_wallet_client;
};
diff --git a/src/wallet/test/ismine_tests.cpp b/src/wallet/test/ismine_tests.cpp
index d5aed99d99..0ef8b9c4bf 100644
--- a/src/wallet/test/ismine_tests.cpp
+++ b/src/wallet/test/ismine_tests.cpp
@@ -27,8 +27,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
CKey uncompressedKey;
uncompressedKey.MakeNewKey(false);
CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
- NodeContext node;
- std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
+ std::unique_ptr<interfaces::Chain>& chain = m_node.chain;
CScript scriptPubKey;
isminetype result;
diff --git a/src/wallet/test/scriptpubkeyman_tests.cpp b/src/wallet/test/scriptpubkeyman_tests.cpp
index f7c1337b0d..347a436429 100644
--- a/src/wallet/test/scriptpubkeyman_tests.cpp
+++ b/src/wallet/test/scriptpubkeyman_tests.cpp
@@ -17,9 +17,7 @@ BOOST_FIXTURE_TEST_SUITE(scriptpubkeyman_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(CanProvide)
{
// Set up wallet and keyman variables.
- NodeContext node;
- std::unique_ptr<interfaces::Chain> chain = interfaces::MakeChain(node);
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
LegacyScriptPubKeyMan& keyman = *wallet.GetOrCreateLegacyScriptPubKeyMan();
// Make a 1 of 2 multisig script
diff --git a/src/wallet/test/wallet_test_fixture.cpp b/src/wallet/test/wallet_test_fixture.cpp
index 4d6f427618..badf2eb459 100644
--- a/src/wallet/test/wallet_test_fixture.cpp
+++ b/src/wallet/test/wallet_test_fixture.cpp
@@ -6,10 +6,10 @@
WalletTestingSetup::WalletTestingSetup(const std::string& chainName)
: TestingSetup(chainName),
- m_wallet(m_chain.get(), "", CreateMockWalletDatabase())
+ m_wallet(m_node.chain.get(), "", CreateMockWalletDatabase())
{
bool fFirstRun;
m_wallet.LoadWallet(fFirstRun);
- m_chain_notifications_handler = m_chain->handleNotifications({ &m_wallet, [](CWallet*) {} });
+ m_chain_notifications_handler = m_node.chain->handleNotifications({ &m_wallet, [](CWallet*) {} });
m_wallet_client->registerRpcs();
}
diff --git a/src/wallet/test/wallet_test_fixture.h b/src/wallet/test/wallet_test_fixture.h
index ba8a5ff1f3..ab7fb8c42b 100644
--- a/src/wallet/test/wallet_test_fixture.h
+++ b/src/wallet/test/wallet_test_fixture.h
@@ -20,8 +20,7 @@
struct WalletTestingSetup : public TestingSetup {
explicit WalletTestingSetup(const std::string& chainName = CBaseChainParams::MAIN);
- std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
- std::unique_ptr<interfaces::WalletClient> m_wallet_client = interfaces::MakeWalletClient(*m_chain, *Assert(m_node.args));
+ std::unique_ptr<interfaces::WalletClient> m_wallet_client = interfaces::MakeWalletClient(*m_node.chain, *Assert(m_node.args));
CWallet m_wallet;
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
};
diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp
index 4911af08c6..eb0bbb6ccc 100644
--- a/src/wallet/test/wallet_tests.cpp
+++ b/src/wallet/test/wallet_tests.cpp
@@ -83,12 +83,9 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CBlockIndex* newTip = ::ChainActive().Tip();
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
-
// Verify ScanForWalletTransactions fails to read an unknown start block.
{
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -107,7 +104,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions picks up transactions in both the old
// and new block files.
{
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -133,7 +130,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions only picks transactions in the new block
// file.
{
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -158,7 +155,7 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
// Verify ScanForWalletTransactions scans no blocks.
{
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
LOCK(wallet.cs_wallet);
wallet.SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -183,9 +180,6 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
CBlockIndex* newTip = ::ChainActive().Tip();
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
-
// Prune the older block file.
{
LOCK(cs_main);
@@ -197,7 +191,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
// before the missing block, and success for a key whose creation time is
// after.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", CreateDummyWalletDatabase());
wallet->SetupLegacyScriptPubKeyMan();
WITH_LOCK(wallet->cs_wallet, wallet->SetLastBlockProcessed(newTip->nHeight, newTip->GetBlockHash()));
AddWallet(wallet);
@@ -255,14 +249,11 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
SetMockTime(KEY_TIME);
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
-
std::string backup_file = (GetDataDir() / "wallet.backup").string();
// Import key into wallet and call dumpwallet to create backup file.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", CreateDummyWalletDatabase());
{
auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan();
LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore);
@@ -284,7 +275,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
// were scanned, and no prior blocks were scanned.
{
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", CreateDummyWalletDatabase());
LOCK(wallet->cs_wallet);
wallet->SetupLegacyScriptPubKeyMan();
@@ -317,10 +308,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
// debit functions.
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
{
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
-
- CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
+ CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
auto spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
CWalletTx wtx(&wallet, m_coinbase_txns.back());
@@ -495,7 +483,7 @@ public:
ListCoinsTestingSetup()
{
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
- wallet = MakeUnique<CWallet>(m_chain.get(), "", CreateMockWalletDatabase());
+ wallet = MakeUnique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
{
LOCK2(wallet->cs_wallet, ::cs_main);
wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
@@ -545,7 +533,6 @@ public:
return it->second;
}
- std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
std::unique_ptr<CWallet> wallet;
};
@@ -612,9 +599,7 @@ BOOST_FIXTURE_TEST_CASE(ListCoins, ListCoinsTestingSetup)
BOOST_FIXTURE_TEST_CASE(wallet_disableprivkeys, TestChain100Setup)
{
- NodeContext node;
- auto chain = interfaces::MakeChain(node);
- std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(chain.get(), "", CreateDummyWalletDatabase());
+ std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(m_node.chain.get(), "", CreateDummyWalletDatabase());
wallet->SetupLegacyScriptPubKeyMan();
wallet->SetMinVersion(FEATURE_LATEST);
wallet->SetWalletFlag(WALLET_FLAG_DISABLE_PRIVATE_KEYS);
@@ -709,8 +694,7 @@ BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup)
BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
{
// Create new wallet with known key and unload it.
- auto chain = interfaces::MakeChain(m_node);
- auto wallet = TestLoadWallet(*chain);
+ auto wallet = TestLoadWallet(*m_node.chain);
CKey key;
key.MakeNewKey(true);
AddKey(*wallet, key);
@@ -745,12 +729,12 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
auto block_tx = TestSimpleSpend(*m_coinbase_txns[0], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
auto mempool_tx = TestSimpleSpend(*m_coinbase_txns[1], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
- BOOST_CHECK(chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
+ BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
// Reload wallet and make sure new transactions are detected despite events
// being blocked
- wallet = TestLoadWallet(*chain);
+ wallet = TestLoadWallet(*m_node.chain);
BOOST_CHECK(rescan_completed);
BOOST_CHECK_EQUAL(addtx_count, 2);
{
@@ -783,12 +767,12 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
block_tx = TestSimpleSpend(*m_coinbase_txns[2], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
m_coinbase_txns.push_back(CreateAndProcessBlock({block_tx}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
mempool_tx = TestSimpleSpend(*m_coinbase_txns[3], 0, coinbaseKey, GetScriptForRawPubKey(key.GetPubKey()));
- BOOST_CHECK(chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
+ BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), DEFAULT_TRANSACTION_MAXFEE, false, error));
LEAVE_CRITICAL_SECTION(wallet->wallet()->cs_wallet);
SyncWithValidationInterfaceQueue();
ENTER_CRITICAL_SECTION(wallet->wallet()->cs_wallet);
});
- wallet = TestLoadWallet(*chain);
+ wallet = TestLoadWallet(*m_node.chain);
BOOST_CHECK_EQUAL(addtx_count, 4);
{
LOCK(wallet->cs_wallet);
@@ -802,8 +786,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)
{
- auto chain = interfaces::MakeChain(m_node);
- auto wallet = TestLoadWallet(*chain);
+ auto wallet = TestLoadWallet(*m_node.chain);
CKey key;
key.MakeNewKey(true);
AddKey(*wallet, key);
diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp
index 65b54f39b4..8350d66fa7 100644
--- a/src/wallet/wallet.cpp
+++ b/src/wallet/wallet.cpp
@@ -946,11 +946,12 @@ bool CWallet::LoadToWallet(const uint256& hash, const UpdateWalletTxFn& fill_wtx
}
// If wallet doesn't have a chain (e.g wallet-tool), don't bother to update txn.
if (HaveChain()) {
- Optional<int> block_height = chain().getBlockHeight(wtx.m_confirm.hashBlock);
- if (block_height) {
+ bool active;
+ int height;
+ if (chain().findBlock(wtx.m_confirm.hashBlock, FoundBlock().inActiveChain(active).height(height)) && active) {
// Update cached block height variable since it not stored in the
// serialized transaction.
- wtx.m_confirm.block_height = *block_height;
+ wtx.m_confirm.block_height = height;
} else if (wtx.isConflicted() || wtx.isConfirmed()) {
// If tx block (or conflicting block) was reorged out of chain
// while the wallet was shutdown, change tx status to UNCONFIRMED
@@ -1771,18 +1772,22 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
WalletLogPrintf("Still rescanning. At block %d. Progress=%f\n", block_height, progress_current);
}
+ // Read block data
CBlock block;
- bool next_block;
+ chain().findBlock(block_hash, FoundBlock().data(block));
+
+ // Find next block separately from reading data above, because reading
+ // is slow and there might be a reorg while it is read.
+ bool block_still_active = false;
+ bool next_block = false;
uint256 next_block_hash;
- bool reorg = false;
- if (chain().findBlock(block_hash, FoundBlock().data(block)) && !block.IsNull()) {
+ chain().findBlock(block_hash, FoundBlock().inActiveChain(block_still_active).nextBlock(FoundBlock().inActiveChain(next_block).hash(next_block_hash)));
+
+ if (!block.IsNull()) {
LOCK(cs_wallet);
- next_block = chain().findNextBlock(block_hash, block_height, FoundBlock().hash(next_block_hash), &reorg);
- if (reorg) {
+ if (!block_still_active) {
// Abort scan if current block is no longer active, to prevent
// marking transactions as coming from the wrong block.
- // TODO: This should return success instead of failure, see
- // https://github.com/bitcoin/bitcoin/pull/14711#issuecomment-458342518
result.last_failed_block = block_hash;
result.status = ScanResult::FAILURE;
break;
@@ -1797,13 +1802,12 @@ CWallet::ScanResult CWallet::ScanForWalletTransactions(const uint256& start_bloc
// could not scan block, keep scanning but record this block as the most recent failure
result.last_failed_block = block_hash;
result.status = ScanResult::FAILURE;
- next_block = chain().findNextBlock(block_hash, block_height, FoundBlock().hash(next_block_hash), &reorg);
}
if (max_height && block_height >= *max_height) {
break;
}
{
- if (!next_block || reorg) {
+ if (!next_block) {
// break successfully when rescan has reached the tip, or
// previous block is no longer on the chain due to a reorg
break;
@@ -4058,9 +4062,7 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
if (!time_first_key || time < *time_first_key) time_first_key = time;
}
if (time_first_key) {
- if (Optional<int> first_block = chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, nullptr)) {
- rescan_height = *first_block;
- }
+ chain.findFirstBlockWithTimeAndHeight(*time_first_key - TIMESTAMP_WINDOW, rescan_height, FoundBlock().height(rescan_height));
}
{