mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 20:12:57 +01:00
merge bitcoin#19425: Get rid of more redundant chain methods
This commit is contained in:
parent
3417be57c7
commit
320b4b69ab
@ -17,15 +17,13 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
|
||||
RegTestingSetup test_setup;
|
||||
const auto& ADDRESS_WATCHONLY = ADDRESS_B58T_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 std::optional<std::string> address_mine{add_mine ? std::optional<std::string>{getnewaddress(wallet)} : std::nullopt};
|
||||
if (add_watchonly) importaddress(wallet, ADDRESS_WATCHONLY);
|
||||
|
@ -55,6 +55,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; }
|
||||
@ -64,6 +68,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;
|
||||
};
|
||||
|
||||
@ -88,9 +94,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:
|
||||
@ -101,11 +107,6 @@ public:
|
||||
//! any blocks)
|
||||
virtual std::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 std::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;
|
||||
|
||||
@ -113,13 +114,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 std::optional<int> findFirstBlockWithTimeAndHeight(int64_t time, int height, uint256* hash) = 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.
|
||||
@ -149,11 +143,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;
|
||||
|
@ -469,7 +469,7 @@ public:
|
||||
CoreContext m_context_ref{std::nullopt};
|
||||
};
|
||||
|
||||
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();
|
||||
@ -477,6 +477,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();
|
||||
@ -522,7 +524,6 @@ public:
|
||||
std::shared_ptr<Chain::Notifications> m_notifications;
|
||||
};
|
||||
|
||||
|
||||
class NotificationsHandlerImpl : public Handler
|
||||
{
|
||||
public:
|
||||
@ -588,49 +589,34 @@ public:
|
||||
std::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 std::nullopt;
|
||||
}
|
||||
std::optional<int> getBlockHeight(const uint256& hash) override
|
||||
{
|
||||
LOCK(::cs_main);
|
||||
CBlockIndex* block = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
if (block && ::ChainActive().Contains(block)) {
|
||||
return block->nHeight;
|
||||
}
|
||||
return std::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 != nullptr);
|
||||
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;
|
||||
}
|
||||
std::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 std::nullopt;
|
||||
}
|
||||
std::optional<int> findFork(const uint256& hash, std::optional<int>* height) override
|
||||
{
|
||||
LOCK(cs_main);
|
||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||
const CBlockIndex* block = g_chainman.m_blockman.LookupBlockIndex(hash);
|
||||
const CBlockIndex* fork = block ? ::ChainActive().FindFork(block) : nullptr;
|
||||
const CBlockIndex* fork = block ? active.FindFork(block) : nullptr;
|
||||
if (height) {
|
||||
if (block) {
|
||||
*height = block->nHeight;
|
||||
@ -646,12 +632,14 @@ public:
|
||||
CBlockLocator getTipLocator() override
|
||||
{
|
||||
LOCK(cs_main);
|
||||
return ::ChainActive().GetLocator();
|
||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||
return active.GetLocator();
|
||||
}
|
||||
std::optional<int> findLocatorFork(const CBlockLocator& locator) override
|
||||
{
|
||||
LOCK(cs_main);
|
||||
if (CBlockIndex* fork = g_chainman.m_blockman.FindForkInGlobalIndex(::ChainActive(), locator)) {
|
||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||
if (CBlockIndex* fork = g_chainman.m_blockman.FindForkInGlobalIndex(active, locator)) {
|
||||
return fork->nHeight;
|
||||
}
|
||||
return std::nullopt;
|
||||
@ -659,50 +647,49 @@ public:
|
||||
bool checkFinalTx(const CTransaction& tx) override
|
||||
{
|
||||
LOCK(cs_main);
|
||||
return CheckFinalTx(::ChainActive().Tip(), tx);
|
||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||
return CheckFinalTx(active.Tip(), tx);
|
||||
}
|
||||
bool findBlock(const uint256& hash, const FoundBlock& block) override
|
||||
{
|
||||
WAIT_LOCK(cs_main, lock);
|
||||
return FillBlock(g_chainman.m_blockman.LookupBlockIndex(hash), block, lock);
|
||||
const CChain& active = Assert(m_node.chainman)->ActiveChain();
|
||||
return FillBlock(g_chainman.m_blockman.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 = g_chainman.m_blockman.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 = g_chainman.m_blockman.LookupBlockIndex(block_hash);
|
||||
const CBlockIndex* ancestor = g_chainman.m_blockman.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 = g_chainman.m_blockman.LookupBlockIndex(block_hash1);
|
||||
const CBlockIndex* block2 = g_chainman.m_blockman.LookupBlockIndex(block_hash2);
|
||||
const CBlockIndex* ancestor = block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
|
||||
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
|
||||
@ -813,7 +800,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();
|
||||
}
|
||||
|
@ -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) {
|
||||
CValidationState state;
|
||||
@ -120,8 +117,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));
|
||||
|
@ -129,10 +129,7 @@ public:
|
||||
CTransactionBuilderTestSetup()
|
||||
{
|
||||
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
||||
node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get());
|
||||
chain = interfaces::MakeChain(node);
|
||||
wallet = std::make_unique<CWallet>(chain.get(), "", CreateMockWalletDatabase());
|
||||
wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
|
||||
wallet->SetupLegacyScriptPubKeyMan();
|
||||
bool firstRun;
|
||||
wallet->LoadWallet(firstRun);
|
||||
@ -153,8 +150,6 @@ public:
|
||||
RemoveWallet(wallet, std::nullopt);
|
||||
}
|
||||
|
||||
NodeContext node;
|
||||
std::shared_ptr<interfaces::Chain> chain;
|
||||
std::shared_ptr<CWallet> wallet;
|
||||
|
||||
CWalletTx& AddTxToChain(uint256 nTxHash)
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
|
@ -28,7 +28,7 @@ BOOST_AUTO_TEST_CASE(ismine_standard)
|
||||
uncompressedKey.MakeNewKey(false);
|
||||
CPubKey uncompressedPubkey = uncompressedKey.GetPubKey();
|
||||
NodeContext node;
|
||||
auto chain = interfaces::MakeChain(node);
|
||||
auto& chain = m_node.chain;
|
||||
|
||||
CScript scriptPubKey;
|
||||
isminetype result;
|
||||
|
@ -7,10 +7,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();
|
||||
}
|
||||
|
@ -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;
|
||||
};
|
||||
|
@ -88,14 +88,9 @@ BOOST_FIXTURE_TEST_CASE(scan_for_wallet_transactions, TestChain100Setup)
|
||||
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
||||
CBlockIndex* newTip = ::ChainActive().Tip();
|
||||
|
||||
NodeContext node;
|
||||
node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get());
|
||||
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());
|
||||
wallet.SetupLegacyScriptPubKeyMan();
|
||||
{
|
||||
LOCK(wallet.cs_wallet);
|
||||
@ -115,7 +110,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());
|
||||
@ -141,7 +136,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());
|
||||
@ -166,7 +161,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());
|
||||
@ -191,11 +186,6 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
|
||||
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
||||
CBlockIndex* newTip = ::ChainActive().Tip();
|
||||
|
||||
NodeContext node;
|
||||
node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get());
|
||||
auto chain = interfaces::MakeChain(node);
|
||||
|
||||
// Prune the older block file.
|
||||
{
|
||||
LOCK(cs_main);
|
||||
@ -207,7 +197,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);
|
||||
@ -265,16 +255,11 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
|
||||
SetMockTime(KEY_TIME);
|
||||
m_coinbase_txns.emplace_back(CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey())).vtx[0]);
|
||||
|
||||
NodeContext node;
|
||||
node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get());
|
||||
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);
|
||||
spk_man->mapKeyMetadata[coinbaseKey.GetPubKey().GetID()].nCreateTime = KEY_TIME;
|
||||
@ -293,7 +278,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();
|
||||
|
||||
@ -402,13 +387,8 @@ BOOST_FIXTURE_TEST_CASE(rpc_getaddressinfo, TestChain100Setup)
|
||||
// debit functions.
|
||||
BOOST_FIXTURE_TEST_CASE(coin_mark_dirty_immature_credit, TestChain100Setup)
|
||||
{
|
||||
NodeContext node;
|
||||
node.fee_estimator = std::make_unique<CBlockPolicyEstimator>();
|
||||
node.mempool = std::make_unique<CTxMemPool>(node.fee_estimator.get());
|
||||
auto chain = interfaces::MakeChain(node);
|
||||
|
||||
CWallet wallet(chain.get(), "", CreateDummyWalletDatabase());
|
||||
auto spk_man = wallet.GetOrCreateLegacyScriptPubKeyMan();
|
||||
CWallet wallet(m_node.chain.get(), "", CreateDummyWalletDatabase());
|
||||
auto spk_man = wallet.GetLegacyScriptPubKeyMan();
|
||||
CWalletTx wtx(&wallet, m_coinbase_txns.back());
|
||||
|
||||
LOCK2(wallet.cs_wallet, spk_man->cs_KeyStore);
|
||||
@ -589,7 +569,7 @@ public:
|
||||
ListCoinsTestingSetup()
|
||||
{
|
||||
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
||||
wallet = std::make_unique<CWallet>(m_chain.get(), "", CreateMockWalletDatabase());
|
||||
wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
|
||||
@ -636,7 +616,6 @@ public:
|
||||
return it->second;
|
||||
}
|
||||
|
||||
std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
|
||||
std::unique_ptr<CWallet> wallet;
|
||||
};
|
||||
|
||||
@ -727,7 +706,7 @@ public:
|
||||
CreateTransactionTestSetup()
|
||||
{
|
||||
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
|
||||
wallet = std::make_unique<CWallet>(m_chain.get(), "", CreateMockWalletDatabase());
|
||||
wallet = std::make_unique<CWallet>(m_node.chain.get(), "", CreateMockWalletDatabase());
|
||||
bool firstRun;
|
||||
wallet->LoadWallet(firstRun);
|
||||
AddWallet(wallet);
|
||||
@ -742,8 +721,6 @@ public:
|
||||
BOOST_CHECK_EQUAL(result.status, CWallet::ScanResult::SUCCESS);
|
||||
}
|
||||
|
||||
std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
|
||||
|
||||
~CreateTransactionTestSetup()
|
||||
{
|
||||
RemoveWallet(wallet, std::nullopt);
|
||||
@ -1238,8 +1215,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWalletFromFile, TestChain100Setup)
|
||||
{
|
||||
gArgs.ForceSetArg("-unsafesqlitesync", "1");
|
||||
// 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);
|
||||
@ -1274,12 +1250,12 @@ BOOST_FIXTURE_TEST_CASE(CreateWalletFromFile, 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), error, DEFAULT_TRANSACTION_MAXFEE, false));
|
||||
BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), error, DEFAULT_TRANSACTION_MAXFEE, false));
|
||||
|
||||
|
||||
// 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);
|
||||
{
|
||||
@ -1311,14 +1287,14 @@ BOOST_FIXTURE_TEST_CASE(CreateWalletFromFile, 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), error, DEFAULT_TRANSACTION_MAXFEE, false));
|
||||
BOOST_CHECK(m_node.chain->broadcastTransaction(MakeTransactionRef(mempool_tx), error, DEFAULT_TRANSACTION_MAXFEE, false));
|
||||
LEAVE_CRITICAL_SECTION(cs_wallets);
|
||||
LEAVE_CRITICAL_SECTION(wallet->wallet()->cs_wallet);
|
||||
SyncWithValidationInterfaceQueue();
|
||||
ENTER_CRITICAL_SECTION(wallet->wallet()->cs_wallet);
|
||||
ENTER_CRITICAL_SECTION(cs_wallets);
|
||||
});
|
||||
wallet = TestLoadWallet(*chain);
|
||||
wallet = TestLoadWallet(*m_node.chain);
|
||||
BOOST_CHECK_EQUAL(addtx_count, 4);
|
||||
{
|
||||
LOCK(wallet->cs_wallet);
|
||||
|
@ -957,11 +957,12 @@ void CWallet::LoadToWallet(CWalletTx& wtxIn)
|
||||
{
|
||||
// If wallet doesn't have a chain (e.g dash-wallet), don't bother to update txn.
|
||||
if (HaveChain()) {
|
||||
std::optional<int> block_height = chain().getBlockHeight(wtxIn.m_confirm.hashBlock);
|
||||
if (block_height) {
|
||||
bool active;
|
||||
int height;
|
||||
if (chain().findBlock(wtxIn.m_confirm.hashBlock, FoundBlock().inActiveChain(active).height(height)) && active) {
|
||||
// Update cached block height variable since it not stored in the
|
||||
// serialized transaction.
|
||||
wtxIn.m_confirm.block_height = *block_height;
|
||||
wtxIn.m_confirm.block_height = height;
|
||||
} else if (wtxIn.isConflicted() || wtxIn.isConfirmed()) {
|
||||
// If tx block (or conflicting block) was reorged out of chain
|
||||
// while the wallet was shutdown, change tx status to UNCONFIRMED
|
||||
@ -1930,18 +1931,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;
|
||||
@ -1957,13 +1962,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;
|
||||
@ -4739,9 +4743,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 (std::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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -5065,8 +5067,10 @@ bool CWalletTx::IsChainLocked() const
|
||||
if (!fIsChainlocked) {
|
||||
assert(pwallet != nullptr);
|
||||
AssertLockHeld(pwallet->cs_wallet);
|
||||
if (std::optional<int> height = pwallet->chain().getBlockHeight(m_confirm.hashBlock)) {
|
||||
fIsChainlocked = llmq::chainLocksHandler->HasChainLock(*height, m_confirm.hashBlock);
|
||||
bool active;
|
||||
int height;
|
||||
if (pwallet->chain().findBlock(m_confirm.hashBlock, FoundBlock().inActiveChain(active).height(height)) && active) {
|
||||
fIsChainlocked = llmq::chainLocksHandler->HasChainLock(height, m_confirm.hashBlock);
|
||||
}
|
||||
}
|
||||
return fIsChainlocked;
|
||||
|
Loading…
Reference in New Issue
Block a user