Skip to content

Commit be164f9

Browse files
committed
refactor: Add CWallet:::AttachChain method
This commit does not change behavior, it just moves code from CWallet::CreateWalletFromFile to CWallet:::AttachChain so it can be updated in the next commit. This commit is most easily reviewed with "git diff -w --color-moved=dimmed_zebra" or by diffing CWallet:::AttachChain against the previous code with an external diff tool.
1 parent 920cb9a commit be164f9

File tree

5 files changed

+102
-75
lines changed

5 files changed

+102
-75
lines changed

src/bench/wallet_balance.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
3232
bool first_run;
3333
if (wallet.LoadWallet(first_run) != DBErrors::LOAD_OK) assert(false);
3434
}
35-
auto handler = chain->handleNotifications({&wallet, [](CWallet*) {}});
35+
CWallet::AttachChain({&wallet, [](CWallet*) {}});
3636

3737
const Optional<std::string> address_mine{add_mine ? Optional<std::string>{getnewaddress(wallet)} : nullopt};
3838
if (add_watchonly) importaddress(wallet, ADDRESS_WATCHONLY);

src/wallet/test/wallet_test_fixture.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName)
1010
{
1111
bool fFirstRun;
1212
m_wallet.LoadWallet(fFirstRun);
13-
m_chain_notifications_handler = m_chain->handleNotifications({ &m_wallet, [](CWallet*) {} });
13+
CWallet::AttachChain({ &m_wallet, [](CWallet*) {} });
1414
m_wallet_client->registerRpcs();
1515
}

src/wallet/test/wallet_test_fixture.h

-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ struct WalletTestingSetup : public TestingSetup {
2323
std::unique_ptr<interfaces::Chain> m_chain = interfaces::MakeChain(m_node);
2424
std::unique_ptr<interfaces::WalletClient> m_wallet_client = interfaces::MakeWalletClient(*m_chain, *Assert(m_node.args));
2525
CWallet m_wallet;
26-
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
2726
};
2827

2928
#endif // BITCOIN_WALLET_TEST_WALLET_TEST_FIXTURE_H

src/wallet/wallet.cpp

+90-72
Original file line numberDiff line numberDiff line change
@@ -4006,6 +4006,91 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
40064006

40074007
LOCK(walletInstance->cs_wallet);
40084008

4009+
CWallet::ScanStatus scan_status = CWallet::AttachChain(walletInstance, !fFirstRun);
4010+
if (scan_status == CWallet::ScanStatus::FAILED) {
4011+
error = _("Failed to rescan the wallet during initialization");
4012+
return nullptr;
4013+
} else if (scan_status == CWallet::ScanStatus::MISSING_BLOCKS) {
4014+
// We can't rescan beyond non-pruned blocks, stop and throw an error.
4015+
// This might happen if a user uses an old wallet within a pruned node
4016+
// or if they ran -disablewallet for a longer time, then decided to re-enable
4017+
// Exit early and print an error.
4018+
// If a block is pruned after this check, we will load the wallet,
4019+
// but fail the rescan with a generic error.
4020+
error = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
4021+
return nullptr;
4022+
}
4023+
4024+
{
4025+
LOCK(cs_wallets);
4026+
for (auto& load_wallet : g_load_wallet_fns) {
4027+
load_wallet(interfaces::MakeWallet(walletInstance));
4028+
}
4029+
}
4030+
4031+
walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
4032+
4033+
{
4034+
walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
4035+
walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
4036+
walletInstance->WalletLogPrintf("m_address_book.size() = %u\n", walletInstance->m_address_book.size());
4037+
}
4038+
4039+
return walletInstance;
4040+
}
4041+
4042+
const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest, bool allow_change) const
4043+
{
4044+
const auto& address_book_it = m_address_book.find(dest);
4045+
if (address_book_it == m_address_book.end()) return nullptr;
4046+
if ((!allow_change) && address_book_it->second.IsChange()) {
4047+
return nullptr;
4048+
}
4049+
return &address_book_it->second;
4050+
}
4051+
4052+
bool CWallet::UpgradeWallet(int version, bilingual_str& error, std::vector<bilingual_str>& warnings)
4053+
{
4054+
int prev_version = GetVersion();
4055+
int nMaxVersion = version;
4056+
if (nMaxVersion == 0) // the -upgradewallet without argument case
4057+
{
4058+
WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
4059+
nMaxVersion = FEATURE_LATEST;
4060+
SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
4061+
} else {
4062+
WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
4063+
}
4064+
if (nMaxVersion < GetVersion())
4065+
{
4066+
error = _("Cannot downgrade wallet");
4067+
return false;
4068+
}
4069+
SetMaxVersion(nMaxVersion);
4070+
4071+
LOCK(cs_wallet);
4072+
4073+
// Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
4074+
int max_version = GetVersion();
4075+
if (!CanSupportFeature(FEATURE_HD_SPLIT) && max_version >= FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) {
4076+
error = _("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.");
4077+
return false;
4078+
}
4079+
4080+
for (auto spk_man : GetActiveScriptPubKeyMans()) {
4081+
if (!spk_man->Upgrade(prev_version, error)) {
4082+
return false;
4083+
}
4084+
}
4085+
return true;
4086+
}
4087+
4088+
CWallet::ScanStatus CWallet::AttachChain(std::shared_ptr<CWallet> wallet, bool scan)
4089+
{
4090+
auto& chain = wallet->chain();
4091+
auto& walletInstance = wallet;
4092+
LOCK(walletInstance->cs_wallet);
4093+
40094094
// Register wallet with validationinterface. It's done before rescan to avoid
40104095
// missing block connections between end of rescan and validation subscribing.
40114096
// Because of wallet lock being hold, block connection notifications are going to
@@ -4037,23 +4122,17 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
40374122
walletInstance->m_last_block_processed_height = -1;
40384123
}
40394124

4125+
ScanStatus scan_status = ScanStatus::SKIPPED;
40404126
if (tip_height && *tip_height != rescan_height)
40414127
{
4042-
// We can't rescan beyond non-pruned blocks, stop and throw an error.
4043-
// This might happen if a user uses an old wallet within a pruned node
4044-
// or if they ran -disablewallet for a longer time, then decided to re-enable
40454128
if (chain.havePruned()) {
4046-
// Exit early and print an error.
4047-
// If a block is pruned after this check, we will load the wallet,
4048-
// but fail the rescan with a generic error.
40494129
int block_height = *tip_height;
40504130
while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
40514131
--block_height;
40524132
}
40534133

40544134
if (rescan_height != block_height) {
4055-
error = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
4056-
return nullptr;
4135+
return CWallet::ScanStatus::MISSING_BLOCKS;
40574136
}
40584137
}
40594138

@@ -4077,76 +4156,15 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
40774156
{
40784157
WalletRescanReserver reserver(*walletInstance);
40794158
if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, {} /* max height */, reserver, true /* update */).status)) {
4080-
error = _("Failed to rescan the wallet during initialization");
4081-
return nullptr;
4159+
return CWallet::ScanStatus::FAILED;
40824160
}
4161+
scan_status = ScanStatus::SUCCESS;
40834162
}
40844163
walletInstance->chainStateFlushed(chain.getTipLocator());
40854164
walletInstance->database->IncrementUpdateCounter();
40864165
}
40874166

4088-
{
4089-
LOCK(cs_wallets);
4090-
for (auto& load_wallet : g_load_wallet_fns) {
4091-
load_wallet(interfaces::MakeWallet(walletInstance));
4092-
}
4093-
}
4094-
4095-
walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
4096-
4097-
{
4098-
walletInstance->WalletLogPrintf("setKeyPool.size() = %u\n", walletInstance->GetKeyPoolSize());
4099-
walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
4100-
walletInstance->WalletLogPrintf("m_address_book.size() = %u\n", walletInstance->m_address_book.size());
4101-
}
4102-
4103-
return walletInstance;
4104-
}
4105-
4106-
const CAddressBookData* CWallet::FindAddressBookEntry(const CTxDestination& dest, bool allow_change) const
4107-
{
4108-
const auto& address_book_it = m_address_book.find(dest);
4109-
if (address_book_it == m_address_book.end()) return nullptr;
4110-
if ((!allow_change) && address_book_it->second.IsChange()) {
4111-
return nullptr;
4112-
}
4113-
return &address_book_it->second;
4114-
}
4115-
4116-
bool CWallet::UpgradeWallet(int version, bilingual_str& error, std::vector<bilingual_str>& warnings)
4117-
{
4118-
int prev_version = GetVersion();
4119-
int nMaxVersion = version;
4120-
if (nMaxVersion == 0) // the -upgradewallet without argument case
4121-
{
4122-
WalletLogPrintf("Performing wallet upgrade to %i\n", FEATURE_LATEST);
4123-
nMaxVersion = FEATURE_LATEST;
4124-
SetMinVersion(FEATURE_LATEST); // permanently upgrade the wallet immediately
4125-
} else {
4126-
WalletLogPrintf("Allowing wallet upgrade up to %i\n", nMaxVersion);
4127-
}
4128-
if (nMaxVersion < GetVersion())
4129-
{
4130-
error = _("Cannot downgrade wallet");
4131-
return false;
4132-
}
4133-
SetMaxVersion(nMaxVersion);
4134-
4135-
LOCK(cs_wallet);
4136-
4137-
// Do not upgrade versions to any version between HD_SPLIT and FEATURE_PRE_SPLIT_KEYPOOL unless already supporting HD_SPLIT
4138-
int max_version = GetVersion();
4139-
if (!CanSupportFeature(FEATURE_HD_SPLIT) && max_version >= FEATURE_HD_SPLIT && max_version < FEATURE_PRE_SPLIT_KEYPOOL) {
4140-
error = _("Cannot upgrade a non HD split wallet without upgrading to support pre split keypool. Please use version 169900 or no version specified.");
4141-
return false;
4142-
}
4143-
4144-
for (auto spk_man : GetActiveScriptPubKeyMans()) {
4145-
if (!spk_man->Upgrade(prev_version, error)) {
4146-
return false;
4147-
}
4148-
}
4149-
return true;
4167+
return scan_status;
41504168
}
41514169

41524170
void CWallet::postInitProcess()

src/wallet/wallet.h

+10
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,16 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
794794
/** Registered interfaces::Chain::Notifications handler. */
795795
std::unique_ptr<interfaces::Handler> m_chain_notifications_handler;
796796

797+
/** Result of scanning a chain for new transactions */
798+
enum class ScanStatus { SUCCESS, FAILED, MISSING_BLOCKS, SKIPPED };
799+
800+
/**
801+
* Catch wallet up to current chain, scanning new blocks, updating the best
802+
* block locator and m_last_block_processed, and registering for
803+
* notifications about new blocks and transactions.
804+
*/
805+
static ScanStatus AttachChain(std::shared_ptr<CWallet> wallet, bool scan = true);
806+
797807
/** Interface for accessing chain state. */
798808
interfaces::Chain& chain() const { assert(m_chain); return *m_chain; }
799809

0 commit comments

Comments
 (0)