Merge #19754: wallet, gui: Reload previously loaded wallets on startup

f1ee37319a wallet: Reload previously loaded wallets on GUI startup (Andrew Chow)

Pull request description:

  Enable the GUI to also use the load_on_startup feature. Wallets loaded in the GUI always have load_on_startup=true. When they are unloaded from the GUI, load_on_startup=false.

  To facilitate this change, UpdateWalletSetting is moved into the wallet module and called from within LoadWallet, RemoveWallet, and Createwallet. This change does not actually touch the GUI code but rather the wallet functions that are shared between the GUI and RPC.

ACKs for top commit:
  jonasschnelli:
    Tested ACK f1ee37319a - works as expected. Wallets loaded via bitcoin-cli (in `-server` mode) or through the RPC console won't be loaded on startup but wallets loaded via the GUI menu will.
  kristapsk:
    ACK f1ee37319a, I have tested the code.

Tree-SHA512: f5b44aa763cf761d919015c5fbc0600b72434aa71e3b57007fd7530a29c3da1a9a0c98c4f22cb6cdffba61150a31170056a7d4737625e7b76f6958f3d584da8c
This commit is contained in:
Jonas Schnelli 2020-09-03 18:24:23 +02:00
commit a0a422c34c
No known key found for this signature in database
GPG key ID: 1EB776BB03C7922D
10 changed files with 104 additions and 77 deletions

View file

@ -1,12 +1,15 @@
Configuration Configuration
------------- -------------
The `createwallet`, `loadwallet`, and `unloadwallet` RPCs now accept Wallets created or loaded in the GUI will now be automatically loaded on
`load_on_startup` options that modify bitcoin's dynamic configuration in startup, so they don't need to be manually reloaded next time Bitcoin is
`\<datadir\>/settings.json`, and can add or remove a wallet from the list of started. The list of wallets to load on startup is stored in
wallets automatically loaded at startup. Unless these options are explicitly `\<datadir\>/settings.json` and augments any command line or `bitcoin.conf`
set to true or false, the load on startup wallet list is not modified, so this `-wallet=` settings that specify more wallets to load. Wallets that are
change is backwards compatible. unloaded in the GUI get removed from the settings list so they won't load again
automatically next startup. (#19754)
In the future, the GUI will start updating the same startup wallet list as the The `createwallet`, `loadwallet`, and `unloadwallet` RPCs now accept
RPCs to automatically reopen wallets previously opened in the GUI. `load_on_startup` options to modify the settings list. Unless these options are
explicitly set to true or false, the list is not modified, so the RPC methods
remain backwards compatible. (#15937)

View file

@ -446,7 +446,7 @@ public:
CAmount getDefaultMaxTxFee() override { return m_wallet->m_default_max_tx_fee; } CAmount getDefaultMaxTxFee() override { return m_wallet->m_default_max_tx_fee; }
void remove() override void remove() override
{ {
RemoveWallet(m_wallet); RemoveWallet(m_wallet, false /* load_on_start */);
} }
bool isLegacy() override { return m_wallet->IsLegacy(); } bool isLegacy() override { return m_wallet->IsLegacy(); }
std::unique_ptr<Handler> handleUnload(UnloadFn fn) override std::unique_ptr<Handler> handleUnload(UnloadFn fn) override
@ -517,12 +517,12 @@ public:
std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, WalletCreationStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings) override std::unique_ptr<Wallet> createWallet(const std::string& name, const SecureString& passphrase, uint64_t wallet_creation_flags, WalletCreationStatus& status, bilingual_str& error, std::vector<bilingual_str>& warnings) override
{ {
std::shared_ptr<CWallet> wallet; std::shared_ptr<CWallet> wallet;
status = CreateWallet(*m_context.chain, passphrase, wallet_creation_flags, name, error, warnings, wallet); status = CreateWallet(*m_context.chain, passphrase, wallet_creation_flags, name, true /* load_on_start */, error, warnings, wallet);
return MakeWallet(std::move(wallet)); return MakeWallet(std::move(wallet));
} }
std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override std::unique_ptr<Wallet> loadWallet(const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings) override
{ {
return MakeWallet(LoadWallet(*m_context.chain, WalletLocation(name), error, warnings)); return MakeWallet(LoadWallet(*m_context.chain, WalletLocation(name), true /* load_on_start */, error, warnings));
} }
std::string getWalletDir() override std::string getWalletDir() override
{ {

View file

@ -112,7 +112,7 @@ void TestAddAddressesToSendBook(interfaces::Node& node)
ClientModel clientModel(node, &optionsModel); ClientModel clientModel(node, &optionsModel);
AddWallet(wallet); AddWallet(wallet);
WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get()); WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get());
RemoveWallet(wallet); RemoveWallet(wallet, nullopt);
EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress); EditAddressDialog editAddressDialog(EditAddressDialog::NewSendingAddress);
editAddressDialog.setModel(walletModel.getAddressTableModel()); editAddressDialog.setModel(walletModel.getAddressTableModel());

View file

@ -167,7 +167,7 @@ void TestGUI(interfaces::Node& node)
ClientModel clientModel(node, &optionsModel); ClientModel clientModel(node, &optionsModel);
AddWallet(wallet); AddWallet(wallet);
WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get()); WalletModel walletModel(interfaces::MakeWallet(wallet), clientModel, platformStyle.get());
RemoveWallet(wallet); RemoveWallet(wallet, nullopt);
sendCoinsDialog.setModel(&walletModel); sendCoinsDialog.setModel(&walletModel);
transactionView.setModel(&walletModel); transactionView.setModel(&walletModel);

View file

@ -118,30 +118,8 @@ void UnloadWallets()
while (!wallets.empty()) { while (!wallets.empty()) {
auto wallet = wallets.back(); auto wallet = wallets.back();
wallets.pop_back(); wallets.pop_back();
RemoveWallet(wallet); std::vector<bilingual_str> warnings;
RemoveWallet(wallet, nullopt, warnings);
UnloadWallet(std::move(wallet)); UnloadWallet(std::move(wallet));
} }
} }
bool AddWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
{
util::SettingsValue setting_value = chain.getRwSetting("wallet");
if (!setting_value.isArray()) setting_value.setArray();
for (const util::SettingsValue& value : setting_value.getValues()) {
if (value.isStr() && value.get_str() == wallet_name) return true;
}
setting_value.push_back(wallet_name);
return chain.updateRwSetting("wallet", setting_value);
}
bool RemoveWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
{
util::SettingsValue setting_value = chain.getRwSetting("wallet");
if (!setting_value.isArray()) return true;
util::SettingsValue new_value(util::SettingsValue::VARR);
for (const util::SettingsValue& value : setting_value.getValues()) {
if (!value.isStr() || value.get_str() != wallet_name) new_value.push_back(value);
}
if (new_value.size() == setting_value.size()) return true;
return chain.updateRwSetting("wallet", new_value);
}

View file

@ -34,10 +34,4 @@ void StopWallets();
//! Close all wallets. //! Close all wallets.
void UnloadWallets(); void UnloadWallets();
//! Add wallet name to persistent configuration so it will be loaded on startup.
bool AddWalletSetting(interfaces::Chain& chain, const std::string& wallet_name);
//! Remove wallet name from persistent configuration so it will not be loaded on startup.
bool RemoveWalletSetting(interfaces::Chain& chain, const std::string& wallet_name);
#endif // BITCOIN_WALLET_LOAD_H #endif // BITCOIN_WALLET_LOAD_H

View file

@ -230,18 +230,6 @@ static void SetFeeEstimateMode(const CWallet* pwallet, CCoinControl& cc, const U
} }
} }
static void UpdateWalletSetting(interfaces::Chain& chain,
const std::string& wallet_name,
const UniValue& load_on_startup,
std::vector<bilingual_str>& warnings)
{
if (load_on_startup.isTrue() && !AddWalletSetting(chain, wallet_name)) {
warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
} else if (load_on_startup.isFalse() && !RemoveWalletSetting(chain, wallet_name)) {
warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
}
}
static UniValue getnewaddress(const JSONRPCRequest& request) static UniValue getnewaddress(const JSONRPCRequest& request)
{ {
RPCHelpMan{"getnewaddress", RPCHelpMan{"getnewaddress",
@ -2528,11 +2516,10 @@ static UniValue loadwallet(const JSONRPCRequest& request)
bilingual_str error; bilingual_str error;
std::vector<bilingual_str> warnings; std::vector<bilingual_str> warnings;
std::shared_ptr<CWallet> const wallet = LoadWallet(*context.chain, location, error, warnings); Optional<bool> load_on_start = request.params[1].isNull() ? nullopt : Optional<bool>(request.params[1].get_bool());
std::shared_ptr<CWallet> const wallet = LoadWallet(*context.chain, location, load_on_start, error, warnings);
if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error.original); if (!wallet) throw JSONRPCError(RPC_WALLET_ERROR, error.original);
UpdateWalletSetting(*context.chain, location.GetName(), request.params[1], warnings);
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.pushKV("name", wallet->GetName()); obj.pushKV("name", wallet->GetName());
obj.pushKV("warning", Join(warnings, Untranslated("\n")).original); obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
@ -2662,7 +2649,8 @@ static UniValue createwallet(const JSONRPCRequest& request)
bilingual_str error; bilingual_str error;
std::shared_ptr<CWallet> wallet; std::shared_ptr<CWallet> wallet;
WalletCreationStatus status = CreateWallet(*context.chain, passphrase, flags, request.params[0].get_str(), error, warnings, wallet); Optional<bool> load_on_start = request.params[6].isNull() ? nullopt : Optional<bool>(request.params[6].get_bool());
WalletCreationStatus status = CreateWallet(*context.chain, passphrase, flags, request.params[0].get_str(), load_on_start, error, warnings, wallet);
switch (status) { switch (status) {
case WalletCreationStatus::CREATION_FAILED: case WalletCreationStatus::CREATION_FAILED:
throw JSONRPCError(RPC_WALLET_ERROR, error.original); throw JSONRPCError(RPC_WALLET_ERROR, error.original);
@ -2673,8 +2661,6 @@ static UniValue createwallet(const JSONRPCRequest& request)
// no default case, so the compiler can warn about missing cases // no default case, so the compiler can warn about missing cases
} }
UpdateWalletSetting(*context.chain, request.params[0].get_str(), request.params[6], warnings);
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.pushKV("name", wallet->GetName()); obj.pushKV("name", wallet->GetName());
obj.pushKV("warning", Join(warnings, Untranslated("\n")).original); obj.pushKV("warning", Join(warnings, Untranslated("\n")).original);
@ -2717,15 +2703,13 @@ static UniValue unloadwallet(const JSONRPCRequest& request)
// Release the "main" shared pointer and prevent further notifications. // Release the "main" shared pointer and prevent further notifications.
// Note that any attempt to load the same wallet would fail until the wallet // Note that any attempt to load the same wallet would fail until the wallet
// is destroyed (see CheckUniqueFileid). // is destroyed (see CheckUniqueFileid).
if (!RemoveWallet(wallet)) { std::vector<bilingual_str> warnings;
Optional<bool> load_on_start = request.params[1].isNull() ? nullopt : Optional<bool>(request.params[1].get_bool());
if (!RemoveWallet(wallet, load_on_start, warnings)) {
throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded"); throw JSONRPCError(RPC_MISC_ERROR, "Requested wallet already unloaded");
} }
interfaces::Chain& chain = wallet->chain();
std::vector<bilingual_str> warnings;
UnloadWallet(std::move(wallet)); UnloadWallet(std::move(wallet));
UpdateWalletSetting(chain, wallet_name, request.params[1], warnings);
UniValue result(UniValue::VOBJ); UniValue result(UniValue::VOBJ);
result.pushKV("warning", Join(warnings, Untranslated("\n")).original); result.pushKV("warning", Join(warnings, Untranslated("\n")).original);

View file

@ -229,7 +229,7 @@ BOOST_FIXTURE_TEST_CASE(importmulti_rescan, TestChain100Setup)
"downloading and rescanning the relevant blocks (see -reindex and -rescan " "downloading and rescanning the relevant blocks (see -reindex and -rescan "
"options).\"}},{\"success\":true}]", "options).\"}},{\"success\":true}]",
0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW)); 0, oldTip->GetBlockTimeMax(), TIMESTAMP_WINDOW));
RemoveWallet(wallet); RemoveWallet(wallet, nullopt);
} }
} }
@ -275,7 +275,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
request.params.push_back(backup_file); request.params.push_back(backup_file);
::dumpwallet().HandleRequest(request); ::dumpwallet().HandleRequest(request);
RemoveWallet(wallet); RemoveWallet(wallet, nullopt);
} }
// Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME // Call importwallet RPC and verify all blocks with timestamps >= BLOCK_TIME
@ -292,7 +292,7 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup)
AddWallet(wallet); AddWallet(wallet);
wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash()); wallet->SetLastBlockProcessed(::ChainActive().Height(), ::ChainActive().Tip()->GetBlockHash());
::importwallet().HandleRequest(request); ::importwallet().HandleRequest(request);
RemoveWallet(wallet); RemoveWallet(wallet, nullopt);
BOOST_CHECK_EQUAL(wallet->mapWallet.size(), 3U); BOOST_CHECK_EQUAL(wallet->mapWallet.size(), 3U);
BOOST_CHECK_EQUAL(m_coinbase_txns.size(), 103U); BOOST_CHECK_EQUAL(m_coinbase_txns.size(), 103U);

View file

@ -33,6 +33,8 @@
#include <wallet/coincontrol.h> #include <wallet/coincontrol.h>
#include <wallet/fees.h> #include <wallet/fees.h>
#include <univalue.h>
#include <algorithm> #include <algorithm>
#include <assert.h> #include <assert.h>
@ -54,6 +56,42 @@ static RecursiveMutex cs_wallets;
static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets); static std::vector<std::shared_ptr<CWallet>> vpwallets GUARDED_BY(cs_wallets);
static std::list<LoadWalletFn> g_load_wallet_fns GUARDED_BY(cs_wallets); static std::list<LoadWalletFn> g_load_wallet_fns GUARDED_BY(cs_wallets);
bool AddWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
{
util::SettingsValue setting_value = chain.getRwSetting("wallet");
if (!setting_value.isArray()) setting_value.setArray();
for (const util::SettingsValue& value : setting_value.getValues()) {
if (value.isStr() && value.get_str() == wallet_name) return true;
}
setting_value.push_back(wallet_name);
return chain.updateRwSetting("wallet", setting_value);
}
bool RemoveWalletSetting(interfaces::Chain& chain, const std::string& wallet_name)
{
util::SettingsValue setting_value = chain.getRwSetting("wallet");
if (!setting_value.isArray()) return true;
util::SettingsValue new_value(util::SettingsValue::VARR);
for (const util::SettingsValue& value : setting_value.getValues()) {
if (!value.isStr() || value.get_str() != wallet_name) new_value.push_back(value);
}
if (new_value.size() == setting_value.size()) return true;
return chain.updateRwSetting("wallet", new_value);
}
static void UpdateWalletSetting(interfaces::Chain& chain,
const std::string& wallet_name,
Optional<bool> load_on_startup,
std::vector<bilingual_str>& warnings)
{
if (load_on_startup == nullopt) return;
if (load_on_startup.get() && !AddWalletSetting(chain, wallet_name)) {
warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may not be loaded next node startup."));
} else if (!load_on_startup.get() && !RemoveWalletSetting(chain, wallet_name)) {
warnings.emplace_back(Untranslated("Wallet load on startup setting could not be updated, so wallet may still be loaded next node startup."));
}
}
bool AddWallet(const std::shared_ptr<CWallet>& wallet) bool AddWallet(const std::shared_ptr<CWallet>& wallet)
{ {
LOCK(cs_wallets); LOCK(cs_wallets);
@ -65,18 +103,32 @@ bool AddWallet(const std::shared_ptr<CWallet>& wallet)
return true; return true;
} }
bool RemoveWallet(const std::shared_ptr<CWallet>& wallet) bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, Optional<bool> load_on_start, std::vector<bilingual_str>& warnings)
{ {
assert(wallet); assert(wallet);
interfaces::Chain& chain = wallet->chain();
std::string name = wallet->GetName();
// Unregister with the validation interface which also drops shared ponters. // Unregister with the validation interface which also drops shared ponters.
wallet->m_chain_notifications_handler.reset(); wallet->m_chain_notifications_handler.reset();
LOCK(cs_wallets); LOCK(cs_wallets);
std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet); std::vector<std::shared_ptr<CWallet>>::iterator i = std::find(vpwallets.begin(), vpwallets.end(), wallet);
if (i == vpwallets.end()) return false; if (i == vpwallets.end()) return false;
vpwallets.erase(i); vpwallets.erase(i);
// Write the wallet setting
UpdateWalletSetting(chain, name, load_on_start, warnings);
return true; return true;
} }
bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, Optional<bool> load_on_start)
{
std::vector<bilingual_str> warnings;
return RemoveWallet(wallet, load_on_start, warnings);
}
std::vector<std::shared_ptr<CWallet>> GetWallets() std::vector<std::shared_ptr<CWallet>> GetWallets()
{ {
LOCK(cs_wallets); LOCK(cs_wallets);
@ -148,7 +200,7 @@ void UnloadWallet(std::shared_ptr<CWallet>&& wallet)
} }
namespace { namespace {
std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const WalletLocation& location, bilingual_str& error, std::vector<bilingual_str>& warnings) std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const WalletLocation& location, Optional<bool> load_on_start, bilingual_str& error, std::vector<bilingual_str>& warnings)
{ {
try { try {
if (!CWallet::Verify(chain, location, error, warnings)) { if (!CWallet::Verify(chain, location, error, warnings)) {
@ -163,6 +215,10 @@ std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const Wall
} }
AddWallet(wallet); AddWallet(wallet);
wallet->postInitProcess(); wallet->postInitProcess();
// Write the wallet setting
UpdateWalletSetting(chain, location.GetName(), load_on_start, warnings);
return wallet; return wallet;
} catch (const std::runtime_error& e) { } catch (const std::runtime_error& e) {
error = Untranslated(e.what()); error = Untranslated(e.what());
@ -171,19 +227,19 @@ std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const Wall
} }
} // namespace } // namespace
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, bilingual_str& error, std::vector<bilingual_str>& warnings) std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, Optional<bool> load_on_start, bilingual_str& error, std::vector<bilingual_str>& warnings)
{ {
auto result = WITH_LOCK(g_loading_wallet_mutex, return g_loading_wallet_set.insert(location.GetName())); auto result = WITH_LOCK(g_loading_wallet_mutex, return g_loading_wallet_set.insert(location.GetName()));
if (!result.second) { if (!result.second) {
error = Untranslated("Wallet already being loading."); error = Untranslated("Wallet already being loading.");
return nullptr; return nullptr;
} }
auto wallet = LoadWalletInternal(chain, location, error, warnings); auto wallet = LoadWalletInternal(chain, location, load_on_start, error, warnings);
WITH_LOCK(g_loading_wallet_mutex, g_loading_wallet_set.erase(result.first)); WITH_LOCK(g_loading_wallet_mutex, g_loading_wallet_set.erase(result.first));
return wallet; return wallet;
} }
WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, std::shared_ptr<CWallet>& result) WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, Optional<bool> load_on_start, bilingual_str& error, std::vector<bilingual_str>& warnings, std::shared_ptr<CWallet>& result)
{ {
// Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted // Indicate that the wallet is actually supposed to be blank and not just blank to make it encrypted
bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET); bool create_blank = (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET);
@ -254,6 +310,10 @@ WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString&
AddWallet(wallet); AddWallet(wallet);
wallet->postInitProcess(); wallet->postInitProcess();
result = wallet; result = wallet;
// Write the wallet settings
UpdateWalletSetting(chain, name, load_on_start, warnings);
return WalletCreationStatus::SUCCESS; return WalletCreationStatus::SUCCESS;
} }

View file

@ -50,10 +50,11 @@ struct bilingual_str;
void UnloadWallet(std::shared_ptr<CWallet>&& wallet); void UnloadWallet(std::shared_ptr<CWallet>&& wallet);
bool AddWallet(const std::shared_ptr<CWallet>& wallet); bool AddWallet(const std::shared_ptr<CWallet>& wallet);
bool RemoveWallet(const std::shared_ptr<CWallet>& wallet); bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, Optional<bool> load_on_start, std::vector<bilingual_str>& warnings);
bool RemoveWallet(const std::shared_ptr<CWallet>& wallet, Optional<bool> load_on_start);
std::vector<std::shared_ptr<CWallet>> GetWallets(); std::vector<std::shared_ptr<CWallet>> GetWallets();
std::shared_ptr<CWallet> GetWallet(const std::string& name); std::shared_ptr<CWallet> GetWallet(const std::string& name);
std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, bilingual_str& error, std::vector<bilingual_str>& warnings); std::shared_ptr<CWallet> LoadWallet(interfaces::Chain& chain, const WalletLocation& location, Optional<bool> load_on_start, bilingual_str& error, std::vector<bilingual_str>& warnings);
std::unique_ptr<interfaces::Handler> HandleLoadWallet(LoadWalletFn load_wallet); std::unique_ptr<interfaces::Handler> HandleLoadWallet(LoadWalletFn load_wallet);
enum class WalletCreationStatus { enum class WalletCreationStatus {
@ -62,7 +63,7 @@ enum class WalletCreationStatus {
ENCRYPTION_FAILED ENCRYPTION_FAILED
}; };
WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, bilingual_str& error, std::vector<bilingual_str>& warnings, std::shared_ptr<CWallet>& result); WalletCreationStatus CreateWallet(interfaces::Chain& chain, const SecureString& passphrase, uint64_t wallet_creation_flags, const std::string& name, Optional<bool> load_on_start, bilingual_str& error, std::vector<bilingual_str>& warnings, std::shared_ptr<CWallet>& result);
//! -paytxfee default //! -paytxfee default
constexpr CAmount DEFAULT_PAY_TX_FEE = 0; constexpr CAmount DEFAULT_PAY_TX_FEE = 0;
@ -1339,4 +1340,11 @@ public:
// be IsAllFromMe). // be IsAllFromMe).
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig = false) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet); int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, bool use_max_sig = false) EXCLUSIVE_LOCKS_REQUIRED(wallet->cs_wallet);
int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig = false); int64_t CalculateMaximumSignedTxSize(const CTransaction &tx, const CWallet *wallet, const std::vector<CTxOut>& txouts, bool use_max_sig = false);
//! Add wallet name to persistent configuration so it will be loaded on startup.
bool AddWalletSetting(interfaces::Chain& chain, const std::string& wallet_name);
//! Remove wallet name from persistent configuration so it will not be loaded on startup.
bool RemoveWalletSetting(interfaces::Chain& chain, const std::string& wallet_name);
#endif // BITCOIN_WALLET_WALLET_H #endif // BITCOIN_WALLET_WALLET_H