mirror of
https://github.com/bitcoin/bitcoin.git
synced 2024-11-19 18:09:47 +01:00
wallet: add FastWalletRescanFilter
class for speeding up rescans
This only supports wallet descriptors right now.
This commit is contained in:
parent
c051026586
commit
70b3513904
@ -5,6 +5,7 @@
|
||||
|
||||
#include <wallet/wallet.h>
|
||||
|
||||
#include <blockfilter.h>
|
||||
#include <chain.h>
|
||||
#include <consensus/amount.h>
|
||||
#include <consensus/consensus.h>
|
||||
@ -261,6 +262,64 @@ std::shared_ptr<CWallet> LoadWalletInternal(WalletContext& context, const std::s
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
class FastWalletRescanFilter
|
||||
{
|
||||
public:
|
||||
FastWalletRescanFilter(const CWallet& wallet) : m_wallet(wallet)
|
||||
{
|
||||
// fast rescanning via block filters is only supported by descriptor wallets right now
|
||||
assert(!m_wallet.IsLegacy());
|
||||
|
||||
// create initial filter with scripts from all ScriptPubKeyMans
|
||||
for (auto spkm : m_wallet.GetAllScriptPubKeyMans()) {
|
||||
auto desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(spkm)};
|
||||
assert(desc_spkm != nullptr);
|
||||
AddScriptPubKeys(desc_spkm);
|
||||
// save each range descriptor's end for possible future filter updates
|
||||
if (desc_spkm->IsHDEnabled()) {
|
||||
m_last_range_ends.emplace(desc_spkm->GetID(), desc_spkm->GetEndRange());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateIfNeeded()
|
||||
{
|
||||
// repopulate filter with new scripts if top-up has happened since last iteration
|
||||
for (const auto& [desc_spkm_id, last_range_end] : m_last_range_ends) {
|
||||
auto desc_spkm{dynamic_cast<DescriptorScriptPubKeyMan*>(m_wallet.GetScriptPubKeyMan(desc_spkm_id))};
|
||||
assert(desc_spkm != nullptr);
|
||||
int32_t current_range_end{desc_spkm->GetEndRange()};
|
||||
if (current_range_end > last_range_end) {
|
||||
AddScriptPubKeys(desc_spkm, last_range_end);
|
||||
m_last_range_ends.at(desc_spkm->GetID()) = current_range_end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<bool> MatchesBlock(const uint256& block_hash) const
|
||||
{
|
||||
return m_wallet.chain().blockFilterMatchesAny(BlockFilterType::BASIC, block_hash, m_filter_set);
|
||||
}
|
||||
|
||||
private:
|
||||
const CWallet& m_wallet;
|
||||
/** Map for keeping track of each range descriptor's last seen end range.
|
||||
* This information is used to detect whether new addresses were derived
|
||||
* (that is, if the current end range is larger than the saved end range)
|
||||
* after processing a block and hence a filter set update is needed to
|
||||
* take possible keypool top-ups into account.
|
||||
*/
|
||||
std::map<uint256, int32_t> m_last_range_ends;
|
||||
GCSFilter::ElementSet m_filter_set;
|
||||
|
||||
void AddScriptPubKeys(const DescriptorScriptPubKeyMan* desc_spkm, int32_t last_range_end = 0)
|
||||
{
|
||||
for (const auto& script_pub_key : desc_spkm->GetScriptPubKeys(last_range_end)) {
|
||||
m_filter_set.emplace(script_pub_key.begin(), script_pub_key.end());
|
||||
}
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
|
||||
std::shared_ptr<CWallet> LoadWallet(WalletContext& context, const std::string& name, std::optional<bool> load_on_start, const DatabaseOptions& options, DatabaseStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings)
|
||||
|
Loading…
Reference in New Issue
Block a user