Merge bitcoin/bitcoin#20773: refactor: split CWallet::Create

489ebb7b34c403a3ce78ff6fb271f8e6ecb47304 wallet: make chain optional for CWallet::Create (Ivan Metlushko)
d73ae939649f3b30e52b5a2cccd7fafd1ab36766 CWallet::Create move chain init message up into calling code (Ivan Metlushko)
44c430ffac940e1d1dd7f5939a495470bc694489 refactor: Add CWallet:::AttachChain method (Russell Yanofsky)
e2a47ce08528dfb39c0340145c6977f6afd587f6 refactor: move first run detection to client code (Ivan Metlushko)

Pull request description:

  This is a followup for https://github.com/bitcoin/bitcoin/pull/20365#discussion_r522265003
  First part of a refactoring with overall goal to simplify `CWallet` and de-duplicate code with `wallettool`

  **Rationale**: split `CWallet::Create` and create `CWallet::AttachChain`.

  `CWallet::AttachChain` takes chain as first parameter on purpose. In future I suggest we can remove `chain` from `CWallet` constructor.

  The second commit is based on be164f9cf89b123f03b926aa980996919924ee64 from #15719 (thanks ryanofsky)

  cc ryanofsky achow101

ACKs for top commit:
  ryanofsky:
    Code review ACK 489ebb7b34c403a3ce78ff6fb271f8e6ecb47304. Only changes since last review were adding a const variable declaration, and implementing suggestion not to move feerate option checks to AttachChain. Thanks for updates and fast responses!

Tree-SHA512: 00235abfe1b00874c56c449adcab8a36582424abb9ba27440bf750af8f3f217b68c11ca74eb30f78a2109ad1d9009315480effc78345e16a3074a1b5d8128721
This commit is contained in:
W. J. van der Laan 2021-05-19 15:57:15 +02:00 committed by pasta
parent d89847f43e
commit 06ea87040b
No known key found for this signature in database
GPG Key ID: 52527BEDABE87984
12 changed files with 106 additions and 87 deletions

View File

@ -21,8 +21,7 @@ static void WalletBalance(benchmark::Bench& bench, const bool set_dirty, const b
CWallet wallet{test_setup->m_node.chain.get(), test_setup->m_node.coinjoin_loader.get(), "", CreateMockWalletDatabase()};
{
wallet.SetupLegacyScriptPubKeyMan();
bool first_run;
if (wallet.LoadWallet(first_run) != DBErrors::LOAD_OK) assert(false);
if (wallet.LoadWallet() != DBErrors::LOAD_OK) assert(false);
}
auto handler = test_setup->m_node.chain->handleNotifications({&wallet, [](CWallet*) {}});

View File

@ -62,8 +62,7 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
node.setContext(&test.m_node);
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), node.context()->coinjoin_loader.get(), "", CreateMockWalletDatabase());
wallet->SetupLegacyScriptPubKeyMan();
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->LoadWallet();
auto build_address = [wallet]() {
CKey key;

View File

@ -110,8 +110,7 @@ void TestGUI(interfaces::Node& node)
node.setContext(&test.m_node);
std::shared_ptr<CWallet> wallet = std::make_shared<CWallet>(node.context()->chain.get(), node.context()->coinjoin_loader.get(), "", CreateMockWalletDatabase());
AddWallet(wallet);
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->LoadWallet();
{
auto spk_man = wallet->GetOrCreateLegacyScriptPubKeyMan();
LOCK2(wallet->cs_wallet, spk_man->cs_KeyStore);

View File

@ -202,8 +202,7 @@ bool CreateFromDump(const std::string& name, const fs::path& wallet_path, biling
std::shared_ptr<CWallet> wallet(new CWallet(nullptr /* chain */, /*coinjoin_loader=*/ nullptr, name, std::move(database)), WalletToolReleaseWallet);
{
LOCK(wallet->cs_wallet);
bool first_run = true;
DBErrors load_wallet_ret = wallet->LoadWallet(first_run);
DBErrors load_wallet_ret = wallet->LoadWallet();
if (load_wallet_ret != DBErrors::LOAD_OK) {
error = strprintf(_("Error creating %s"), name);
return false;

View File

@ -110,7 +110,8 @@ bool LoadWallets(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoi
if (!database && status == DatabaseStatus::FAILED_NOT_FOUND) {
continue;
}
std::shared_ptr<CWallet> pwallet = database ? CWallet::Create(chain, coinjoin_loader, name, std::move(database), options.create_flags, error_string, warnings) : nullptr;
chain.initMessage(_("Loading wallet...").translated);
std::shared_ptr<CWallet> pwallet = database ? CWallet::Create(&chain, coinjoin_loader, name, std::move(database), options.create_flags, error_string, warnings) : nullptr;
if (!warnings.empty()) chain.initWarning(Join(warnings, Untranslated("\n")));
if (!pwallet) {
chain.initError(error_string);

View File

@ -132,8 +132,7 @@ public:
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
wallet = std::make_unique<CWallet>(m_node.chain.get(), m_node.coinjoin_loader.get(), "", CreateMockWalletDatabase());
wallet->SetupLegacyScriptPubKeyMan();
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->LoadWallet();
AddWallet(wallet);
{
LOCK2(wallet->cs_wallet, cs_main);

View File

@ -259,8 +259,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), /* coinjoin_loader = */ nullptr, "", CreateMockWalletDatabase());
wallet->SetupLegacyScriptPubKeyMan();
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->LoadWallet();
LOCK(wallet->cs_wallet);
bool bnb_used;
@ -283,8 +282,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), /* coinjoin_loader = */ nullptr, "", CreateMockWalletDatabase());
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->LoadWallet();
wallet->SetupLegacyScriptPubKeyMan();
LOCK(wallet->cs_wallet);
@ -309,8 +307,7 @@ BOOST_AUTO_TEST_CASE(bnb_search_test)
BOOST_AUTO_TEST_CASE(knapsack_solver_test)
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), /* coinjoin_loader = */ nullptr, "", CreateMockWalletDatabase());
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->LoadWallet();
wallet->SetupLegacyScriptPubKeyMan();
LOCK(wallet->cs_wallet);
@ -591,8 +588,7 @@ BOOST_AUTO_TEST_CASE(knapsack_solver_test)
BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), /* coinjoin_loader = */ nullptr, "", CreateMockWalletDatabase());
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->LoadWallet();
wallet->SetupLegacyScriptPubKeyMan();
LOCK(wallet->cs_wallet);
@ -615,8 +611,7 @@ BOOST_AUTO_TEST_CASE(ApproximateBestSubset)
BOOST_AUTO_TEST_CASE(SelectCoins_test)
{
std::unique_ptr<CWallet> wallet = std::make_unique<CWallet>(m_node.chain.get(), /* coinjoin_loader = */ nullptr, "", CreateMockWalletDatabase());
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->LoadWallet();
wallet->SetupLegacyScriptPubKeyMan();
LOCK(wallet->cs_wallet);

View File

@ -10,8 +10,7 @@ WalletTestingSetup::WalletTestingSetup(const std::string& chainName)
m_wallet_loader{interfaces::MakeWalletLoader(*m_node.chain, m_node.coinjoin_loader, *Assert(m_node.args))},
m_wallet(m_node.chain.get(), m_node.coinjoin_loader.get(), "", CreateMockWalletDatabase())
{
bool fFirstRun;
m_wallet.LoadWallet(fFirstRun);
m_wallet.LoadWallet();
m_chain_notifications_handler = m_node.chain->handleNotifications({ &m_wallet, [](CWallet*) {} });
m_wallet_loader->registerRpcs();
}

View File

@ -51,15 +51,17 @@ namespace {
constexpr CAmount fallbackFee = 1000;
} // anonymous namespace
static std::shared_ptr<CWallet> TestLoadWallet(NodeContext& node)
static std::shared_ptr<CWallet> TestLoadWallet(interfaces::Chain* chain, interfaces::CoinJoin::Loader& coinjoin_loader)
{
DatabaseOptions options;
DatabaseStatus status;
bilingual_str error;
std::vector<bilingual_str> warnings;
auto database = MakeWalletDatabase("", options, status, error);
auto wallet = CWallet::Create(*node.chain, *node.coinjoin_loader, "", std::move(database), options.create_flags, error, warnings);
wallet->postInitProcess();
auto wallet = CWallet::Create(chain, coinjoin_loader, "", std::move(database), options.create_flags, error, warnings);
if (chain) {
wallet->postInitProcess();
}
return wallet;
}
@ -581,8 +583,7 @@ public:
LOCK(wallet->cs_wallet);
wallet->SetLastBlockProcessed(m_node.chainman->ActiveChain().Height(), m_node.chainman->ActiveChain().Tip()->GetBlockHash());
}
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->LoadWallet();
AddKey(*wallet, coinbaseKey);
WalletRescanReserver reserver(*wallet);
reserver.reserve();
@ -715,8 +716,7 @@ public:
{
CreateAndProcessBlock({}, GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
wallet = std::make_unique<CWallet>(m_node.chain.get(), m_node.coinjoin_loader.get(), "", CreateMockWalletDatabase());
bool firstRun;
wallet->LoadWallet(firstRun);
wallet->LoadWallet();
AddWallet(wallet);
AddKey(*wallet, coinbaseKey);
WalletRescanReserver reserver(*wallet);
@ -1232,7 +1232,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
{
gArgs.ForceSetArg("-unsafesqlitesync", "1");
// Create new wallet with known key and unload it.
auto wallet = TestLoadWallet(m_node);
auto wallet = TestLoadWallet(m_node.chain.get(), *m_node.coinjoin_loader);
CKey key;
key.MakeNewKey(true);
AddKey(*wallet, key);
@ -1272,7 +1272,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
// Reload wallet and make sure new transactions are detected despite events
// being blocked
wallet = TestLoadWallet(m_node);
wallet = TestLoadWallet(m_node.chain.get(), *m_node.coinjoin_loader);
BOOST_CHECK(rescan_completed);
BOOST_CHECK_EQUAL(addtx_count, 2);
{
@ -1311,7 +1311,7 @@ BOOST_FIXTURE_TEST_CASE(CreateWallet, TestChain100Setup)
ENTER_CRITICAL_SECTION(wallet->wallet()->cs_wallet);
ENTER_CRITICAL_SECTION(cs_wallets);
});
wallet = TestLoadWallet(m_node);
wallet = TestLoadWallet(m_node.chain.get(), *m_node.coinjoin_loader);
BOOST_CHECK_EQUAL(addtx_count, 4);
{
LOCK(wallet->cs_wallet);
@ -1390,11 +1390,18 @@ BOOST_FIXTURE_TEST_CASE(wallet_descriptor_test, BasicTestingSetup)
BOOST_CHECK_EXCEPTION(vr >> w_desc, std::ios_base::failure, malformed_descriptor);
}
BOOST_FIXTURE_TEST_CASE(CreateWalletWithoutChain, BasicTestingSetup)
{
auto wallet = TestLoadWallet(nullptr, *m_node.coinjoin_loader);
BOOST_CHECK(wallet);
UnloadWallet(std::move(wallet));
}
BOOST_FIXTURE_TEST_CASE(ZapSelectTx, TestChain100Setup)
{
gArgs.ForceSetArg("-unsafesqlitesync", "1");
auto chain = interfaces::MakeChain(m_node);
auto wallet = TestLoadWallet(m_node);
auto wallet = TestLoadWallet(m_node.chain.get(), *m_node.coinjoin_loader);
CKey key;
key.MakeNewKey(true);
AddKey(*wallet, key);

View File

@ -238,7 +238,8 @@ std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, interfaces
return nullptr;
}
std::shared_ptr<CWallet> wallet = CWallet::Create(chain, coinjoin_loader, name, std::move(database), options.create_flags, error, warnings);
chain.initMessage(_("Loading wallet...").translated);
std::shared_ptr<CWallet> wallet = CWallet::Create(&chain, coinjoin_loader, name, std::move(database), options.create_flags, error, warnings);
if (!wallet) {
error = Untranslated("Wallet loading failed.") + Untranslated(" ") + error;
status = DatabaseStatus::FAILED_LOAD;
@ -303,7 +304,8 @@ std::shared_ptr<CWallet> CreateWallet(interfaces::Chain& chain, interfaces::Coin
}
// Make the wallet
std::shared_ptr<CWallet> wallet = CWallet::Create(chain, coinjoin_loader, name, std::move(database), wallet_creation_flags, error, warnings);
chain.initMessage(_("Loading wallet...").translated);
std::shared_ptr<CWallet> wallet = CWallet::Create(&chain, coinjoin_loader, name, std::move(database), wallet_creation_flags, error, warnings);
if (!wallet) {
error = Untranslated("Wallet creation failed.") + Untranslated(" ") + error;
status = DatabaseStatus::FAILED_CREATE;
@ -3966,11 +3968,10 @@ void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
}
}
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
DBErrors CWallet::LoadWallet()
{
LOCK(cs_wallet);
fFirstRunRet = false;
DBErrors nLoadWalletRet = WalletBatch(GetDatabase()).LoadWallet(this);
if (nLoadWalletRet == DBErrors::NEED_REWRITE)
{
@ -3983,9 +3984,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
}
}
// This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys
fFirstRunRet = m_spk_managers.empty() && !IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
if (fFirstRunRet) {
if (m_spk_managers.empty()) {
assert(m_external_spk_managers == nullptr);
assert(m_internal_spk_managers == nullptr);
}
@ -4677,22 +4676,19 @@ std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, cons
return MakeDatabase(wallet_path, options, status, error_string);
}
std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoin_loader, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings)
std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain* chain, interfaces::CoinJoin::Loader& coinjoin_loader, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings)
{
const std::string& walletFile = database->Filename();
chain.initMessage(_("Loading wallet…").translated);
int64_t nStart = GetTimeMillis();
bool fFirstRun = true;
// TODO: Can't use std::make_shared because we need a custom deleter but
// should be possible to use std::allocate_shared.
std::shared_ptr<CWallet> walletInstance(new CWallet(&chain, &coinjoin_loader, name, std::move(database)), ReleaseWallet);
std::shared_ptr<CWallet> walletInstance(new CWallet(chain, &coinjoin_loader, name, std::move(database)), ReleaseWallet);
// TODO: refactor this condition: validation of error looks like workaround
if (!walletInstance->AutoBackupWallet(fs::PathFromString(walletFile), error, warnings) && !error.original.empty()) {
return nullptr;
}
DBErrors nLoadWalletRet = walletInstance->LoadWallet(fFirstRun);
DBErrors nLoadWalletRet = walletInstance->LoadWallet();
if (nLoadWalletRet != DBErrors::LOAD_OK)
{
if (nLoadWalletRet == DBErrors::CORRUPT) {
@ -4720,6 +4716,10 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, interfaces::C
}
}
// This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys
const bool fFirstRun = walletInstance->m_spk_managers.empty() &&
!walletInstance->IsWalletFlagSet(WALLET_FLAG_DISABLE_PRIVATE_KEYS) &&
!walletInstance->IsWalletFlagSet(WALLET_FLAG_BLANK_WALLET);
if (fFirstRun)
{
walletInstance->SetMinVersion(FEATURE_LATEST);
@ -4790,7 +4790,9 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, interfaces::C
}
}
walletInstance->chainStateFlushed(chain.getTipLocator());
if (chain) {
walletInstance->chainStateFlushed(chain->getTipLocator());
}
// Try to create wallet backup right after new wallet was created
bilingual_str strBackupError;
@ -4893,9 +4895,9 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, interfaces::C
_("This is the transaction fee you will pay if you send a transaction."));
}
walletInstance->m_pay_tx_fee = CFeeRate{pay_tx_fee.value(), 1000};
if (walletInstance->m_pay_tx_fee < chain.relayMinFee()) {
if (chain && walletInstance->m_pay_tx_fee < chain->relayMinFee()) {
error = strprintf(_("Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)"),
gArgs.GetArg("-paytxfee", ""), chain.relayMinFee().ToString());
gArgs.GetArg("-paytxfee", ""), chain->relayMinFee().ToString());
return nullptr;
}
}
@ -4908,16 +4910,16 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, interfaces::C
} else if (max_fee.value() > HIGH_MAX_TX_FEE) {
warnings.push_back(_("-maxtxfee is set very high! Fees this large could be paid on a single transaction."));
}
if (CFeeRate{max_fee.value(), 1000} < chain.relayMinFee()) {
if (chain && CFeeRate{max_fee.value(), 1000} < chain->relayMinFee()) {
error = strprintf(_("Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)"),
gArgs.GetArg("-maxtxfee", ""), chain.relayMinFee().ToString());
gArgs.GetArg("-maxtxfee", ""), chain->relayMinFee().ToString());
return nullptr;
}
walletInstance->m_default_max_tx_fee = max_fee.value();
}
if (chain.relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB)
if (chain && chain->relayMinFee().GetFeePerK() > HIGH_TX_FEE_PER_KB)
warnings.push_back(AmountHighWarn("-minrelaytxfee") + Untranslated(" ") +
_("The wallet will avoid paying less than the minimum relay fee."));
@ -4931,6 +4933,41 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, interfaces::C
LOCK(walletInstance->cs_wallet);
if (chain && !AttachChain(walletInstance, *chain, error, warnings)) {
return nullptr;
}
coinjoin_loader.AddWallet(*walletInstance);
{
LOCK(cs_wallets);
for (auto& load_wallet : g_load_wallet_fns) {
load_wallet(interfaces::MakeWallet(walletInstance));
}
}
walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
{
walletInstance->WalletLogPrintf("setExternalKeyPool.size() = %u\n", walletInstance->KeypoolCountExternalKeys());
walletInstance->WalletLogPrintf("GetKeyPoolSize() = %u\n", walletInstance->GetKeyPoolSize());
walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
walletInstance->WalletLogPrintf("m_address_book.size() = %u\n", walletInstance->m_address_book.size());
for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
walletInstance->WalletLogPrintf("nTimeFirstKey = %u\n", spk_man->GetTimeFirstKey());
}
}
return walletInstance;
}
bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, bilingual_str& error, std::vector<bilingual_str>& warnings)
{
LOCK(walletInstance->cs_wallet);
// allow setting the chain if it hasn't been set already but prevent changing it
assert(!walletInstance->m_chain || walletInstance->m_chain == &chain);
walletInstance->m_chain = &chain;
// Register wallet with validationinterface. It's done before rescan to avoid
// missing block connections between end of rescan and validation subscribing.
// Because of wallet lock being hold, block connection notifications are going to
@ -4964,21 +5001,21 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, interfaces::C
if (tip_height && *tip_height != rescan_height)
{
// We can't rescan beyond non-pruned blocks, stop and throw an error.
// This might happen if a user uses an old wallet within a pruned node
// or if they ran -disablewallet for a longer time, then decided to re-enable
if (chain.havePruned()) {
// Exit early and print an error.
// If a block is pruned after this check, we will load the wallet,
// but fail the rescan with a generic error.
int block_height = *tip_height;
while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
--block_height;
}
if (rescan_height != block_height) {
// We can't rescan beyond non-pruned blocks, stop and throw an error.
// This might happen if a user uses an old wallet within a pruned node
// or if they ran -disablewallet for a longer time, then decided to re-enable
// Exit early and print an error.
// If a block is pruned after this check, we will load the wallet,
// but fail the rescan with a generic error.
error = _("Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)");
return nullptr;
return false;
}
}
@ -5003,35 +5040,14 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, interfaces::C
WalletRescanReserver reserver(*walletInstance);
if (!reserver.reserve() || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions(chain.getBlockHash(rescan_height), rescan_height, {} /* max height */, reserver, true /* update */).status)) {
error = _("Failed to rescan the wallet during initialization");
return nullptr;
return false;
}
}
walletInstance->chainStateFlushed(chain.getTipLocator());
walletInstance->GetDatabase().IncrementUpdateCounter();
}
coinjoin_loader.AddWallet(*walletInstance);
{
LOCK(cs_wallets);
for (auto& load_wallet : g_load_wallet_fns) {
load_wallet(interfaces::MakeWallet(walletInstance));
}
}
walletInstance->SetBroadcastTransactions(gArgs.GetBoolArg("-walletbroadcast", DEFAULT_WALLETBROADCAST));
{
walletInstance->WalletLogPrintf("setExternalKeyPool.size() = %u\n", walletInstance->KeypoolCountExternalKeys());
walletInstance->WalletLogPrintf("GetKeyPoolSize() = %u\n", walletInstance->GetKeyPoolSize());
walletInstance->WalletLogPrintf("mapWallet.size() = %u\n", walletInstance->mapWallet.size());
walletInstance->WalletLogPrintf("m_address_book.size() = %u\n", walletInstance->m_address_book.size());
for (auto spk_man : walletInstance->GetAllScriptPubKeyMans()) {
walletInstance->WalletLogPrintf("nTimeFirstKey = %u\n", spk_man->GetTimeFirstKey());
}
}
return walletInstance;
return true;
}
bool CWallet::UpgradeWallet(int version, bilingual_str& error)

View File

@ -847,6 +847,13 @@ private:
bool CreateTransactionInternal(const std::vector<CRecipient>& vecSend, CTransactionRef& tx, CAmount& nFeeRet, int& nChangePosInOut, bilingual_str& error, const CCoinControl& coin_control, FeeCalculation& fee_calc_out, bool sign, int nExtraPayloadSize);
/**
* Catch wallet up to current chain, scanning new blocks, updating the best
* block locator and m_last_block_processed, and registering for
* notifications about new blocks and transactions.
*/
static bool AttachChain(const std::shared_ptr<CWallet>& wallet, interfaces::Chain& chain, bilingual_str& error, std::vector<bilingual_str>& warnings);
public:
/**
* Main wallet lock.
@ -1247,7 +1254,7 @@ public:
CAmount GetChange(const CTransaction& tx) const;
void chainStateFlushed(const CBlockLocator& loc) override;
DBErrors LoadWallet(bool& fFirstRunRet);
DBErrors LoadWallet();
void AutoLockMasternodeCollaterals();
DBErrors ZapSelectTx(std::vector<uint256>& vHashIn, std::vector<uint256>& vHashOut) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet);
@ -1338,7 +1345,7 @@ public:
bool ResendTransaction(const uint256& hashTx);
/* Initializes the wallet, returns a new CWallet instance or a null pointer in case of an error */
static std::shared_ptr<CWallet> Create(interfaces::Chain& chain, interfaces::CoinJoin::Loader& coinjoin_loader, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings);
static std::shared_ptr<CWallet> Create(interfaces::Chain* chain, interfaces::CoinJoin::Loader& coinjoin_loader, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings);
/**
* Wallet post-init setup

View File

@ -64,8 +64,7 @@ static std::shared_ptr<CWallet> MakeWallet(const std::string& name, const fs::pa
std::shared_ptr<CWallet> wallet_instance{new CWallet(/*chain=*/ nullptr, /*coinjoin_loader=*/ nullptr, name, std::move(database)), WalletToolReleaseWallet};
DBErrors load_wallet_ret;
try {
bool first_run;
load_wallet_ret = wallet_instance->LoadWallet(first_run);
load_wallet_ret = wallet_instance->LoadWallet();
} catch (const std::runtime_error&) {
tfm::format(std::cerr, "Error loading %s. Is wallet being used by another process?\n", name);
return nullptr;