@@ -213,7 +213,8 @@ std::shared_ptr<CWallet> LoadWalletInternal(interfaces::Chain& chain, const std:
213
213
return nullptr ;
214
214
}
215
215
216
- std::shared_ptr<CWallet> wallet = CWallet::Create (chain, name, std::move (database), options.create_flags , error, warnings);
216
+ chain.initMessage (_ (" Loading wallet..." ).translated );
217
+ std::shared_ptr<CWallet> wallet = CWallet::Create (&chain, name, std::move (database), options.create_flags , error, warnings);
217
218
if (!wallet) {
218
219
error = Untranslated (" Wallet loading failed." ) + Untranslated (" " ) + error;
219
220
status = DatabaseStatus::FAILED_LOAD;
@@ -292,7 +293,8 @@ std::shared_ptr<CWallet> CreateWallet(interfaces::Chain& chain, const std::strin
292
293
}
293
294
294
295
// Make the wallet
295
- std::shared_ptr<CWallet> wallet = CWallet::Create (chain, name, std::move (database), wallet_creation_flags, error, warnings);
296
+ chain.initMessage (_ (" Loading wallet..." ).translated );
297
+ std::shared_ptr<CWallet> wallet = CWallet::Create (&chain, name, std::move (database), wallet_creation_flags, error, warnings);
296
298
if (!wallet) {
297
299
error = Untranslated (" Wallet creation failed." ) + Untranslated (" " ) + error;
298
300
status = DatabaseStatus::FAILED_CREATE;
@@ -3247,11 +3249,10 @@ void CWallet::CommitTransaction(CTransactionRef tx, mapValue_t mapValue, std::ve
3247
3249
}
3248
3250
}
3249
3251
3250
- DBErrors CWallet::LoadWallet (bool & fFirstRunRet )
3252
+ DBErrors CWallet::LoadWallet ()
3251
3253
{
3252
3254
LOCK (cs_wallet);
3253
3255
3254
- fFirstRunRet = false ;
3255
3256
DBErrors nLoadWalletRet = WalletBatch (GetDatabase ()).LoadWallet (this );
3256
3257
if (nLoadWalletRet == DBErrors::NEED_REWRITE)
3257
3258
{
@@ -3263,9 +3264,7 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
3263
3264
}
3264
3265
}
3265
3266
3266
- // This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys
3267
- fFirstRunRet = m_spk_managers.empty () && !IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !IsWalletFlagSet (WALLET_FLAG_BLANK_WALLET);
3268
- if (fFirstRunRet ) {
3267
+ if (m_spk_managers.empty ()) {
3269
3268
assert (m_external_spk_managers.empty ());
3270
3269
assert (m_internal_spk_managers.empty ());
3271
3270
}
@@ -3886,18 +3885,15 @@ std::unique_ptr<WalletDatabase> MakeWalletDatabase(const std::string& name, cons
3886
3885
return MakeDatabase (wallet_path, options, status, error_string);
3887
3886
}
3888
3887
3889
- std::shared_ptr<CWallet> CWallet::Create (interfaces::Chain& chain, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings)
3888
+ std::shared_ptr<CWallet> CWallet::Create (interfaces::Chain* chain, const std::string& name, std::unique_ptr<WalletDatabase> database, uint64_t wallet_creation_flags, bilingual_str& error, std::vector<bilingual_str>& warnings)
3890
3889
{
3891
3890
const std::string& walletFile = database->Filename ();
3892
3891
3893
- chain.initMessage (_ (" Loading wallet…" ).translated );
3894
-
3895
3892
int64_t nStart = GetTimeMillis ();
3896
- bool fFirstRun = true ;
3897
3893
// TODO: Can't use std::make_shared because we need a custom deleter but
3898
3894
// should be possible to use std::allocate_shared.
3899
- std::shared_ptr<CWallet> walletInstance (new CWallet (& chain, name, std::move (database)), ReleaseWallet);
3900
- DBErrors nLoadWalletRet = walletInstance->LoadWallet (fFirstRun );
3895
+ std::shared_ptr<CWallet> walletInstance (new CWallet (chain, name, std::move (database)), ReleaseWallet);
3896
+ DBErrors nLoadWalletRet = walletInstance->LoadWallet ();
3901
3897
if (nLoadWalletRet != DBErrors::LOAD_OK) {
3902
3898
if (nLoadWalletRet == DBErrors::CORRUPT) {
3903
3899
error = strprintf (_ (" Error loading %s: Wallet corrupted" ), walletFile);
@@ -3924,6 +3920,10 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
3924
3920
}
3925
3921
}
3926
3922
3923
+ // This wallet is in its first run if there are no ScriptPubKeyMans and it isn't blank or no privkeys
3924
+ const bool fFirstRun = walletInstance->m_spk_managers .empty () &&
3925
+ !walletInstance->IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS) &&
3926
+ !walletInstance->IsWalletFlagSet (WALLET_FLAG_BLANK_WALLET);
3927
3927
if (fFirstRun )
3928
3928
{
3929
3929
// ensure this wallet.dat can only be opened by clients supporting HD with chain split and expects no default key
@@ -3952,7 +3952,9 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
3952
3952
}
3953
3953
}
3954
3954
3955
- walletInstance->chainStateFlushed (chain.getTipLocator ());
3955
+ if (chain) {
3956
+ walletInstance->chainStateFlushed (chain->getTipLocator ());
3957
+ }
3956
3958
} else if (wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS) {
3957
3959
// Make it impossible to disable private keys after creation
3958
3960
error = strprintf (_ (" Error loading %s: Private keys can only be disabled during creation" ), walletFile);
@@ -4049,9 +4051,9 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
4049
4051
_ (" This is the transaction fee you will pay if you send a transaction." ));
4050
4052
}
4051
4053
walletInstance->m_pay_tx_fee = CFeeRate (nFeePerK, 1000 );
4052
- if (walletInstance->m_pay_tx_fee < chain. relayMinFee ()) {
4054
+ if (chain && walletInstance->m_pay_tx_fee < chain-> relayMinFee ()) {
4053
4055
error = strprintf (_ (" Invalid amount for -paytxfee=<amount>: '%s' (must be at least %s)" ),
4054
- gArgs .GetArg (" -paytxfee" , " " ), chain. relayMinFee ().ToString ());
4056
+ gArgs .GetArg (" -paytxfee" , " " ), chain-> relayMinFee ().ToString ());
4055
4057
return nullptr ;
4056
4058
}
4057
4059
}
@@ -4065,15 +4067,15 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
4065
4067
if (nMaxFee > HIGH_MAX_TX_FEE) {
4066
4068
warnings.push_back (_ (" -maxtxfee is set very high! Fees this large could be paid on a single transaction." ));
4067
4069
}
4068
- if (CFeeRate (nMaxFee, 1000 ) < chain. relayMinFee ()) {
4070
+ if (chain && CFeeRate (nMaxFee, 1000 ) < chain-> relayMinFee ()) {
4069
4071
error = strprintf (_ (" Invalid amount for -maxtxfee=<amount>: '%s' (must be at least the minrelay fee of %s to prevent stuck transactions)" ),
4070
- gArgs .GetArg (" -maxtxfee" , " " ), chain. relayMinFee ().ToString ());
4072
+ gArgs .GetArg (" -maxtxfee" , " " ), chain-> relayMinFee ().ToString ());
4071
4073
return nullptr ;
4072
4074
}
4073
4075
walletInstance->m_default_max_tx_fee = nMaxFee;
4074
4076
}
4075
4077
4076
- if (chain. relayMinFee ().GetFeePerK () > HIGH_TX_FEE_PER_KB) {
4078
+ if (chain && chain-> relayMinFee ().GetFeePerK () > HIGH_TX_FEE_PER_KB) {
4077
4079
warnings.push_back (AmountHighWarn (" -minrelaytxfee" ) + Untranslated (" " ) +
4078
4080
_ (" The wallet will avoid paying less than the minimum relay fee." ));
4079
4081
}
@@ -4089,6 +4091,35 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
4089
4091
4090
4092
LOCK (walletInstance->cs_wallet );
4091
4093
4094
+ if (chain && !AttachChain (walletInstance, *chain, error, warnings)) {
4095
+ return nullptr ;
4096
+ }
4097
+
4098
+ {
4099
+ LOCK (cs_wallets);
4100
+ for (auto & load_wallet : g_load_wallet_fns) {
4101
+ load_wallet (interfaces::MakeWallet (walletInstance));
4102
+ }
4103
+ }
4104
+
4105
+ walletInstance->SetBroadcastTransactions (gArgs .GetBoolArg (" -walletbroadcast" , DEFAULT_WALLETBROADCAST));
4106
+
4107
+ {
4108
+ walletInstance->WalletLogPrintf (" setKeyPool.size() = %u\n " , walletInstance->GetKeyPoolSize ());
4109
+ walletInstance->WalletLogPrintf (" mapWallet.size() = %u\n " , walletInstance->mapWallet .size ());
4110
+ walletInstance->WalletLogPrintf (" m_address_book.size() = %u\n " , walletInstance->m_address_book .size ());
4111
+ }
4112
+
4113
+ return walletInstance;
4114
+ }
4115
+
4116
+ bool CWallet::AttachChain (const std::shared_ptr<CWallet>& walletInstance, interfaces::Chain& chain, bilingual_str& error, std::vector<bilingual_str>& warnings)
4117
+ {
4118
+ LOCK (walletInstance->cs_wallet );
4119
+ // allow setting the chain if it hasn't been set already but prevent changing it
4120
+ assert (!walletInstance->m_chain || walletInstance->m_chain == &chain);
4121
+ walletInstance->m_chain = &chain;
4122
+
4092
4123
// Register wallet with validationinterface. It's done before rescan to avoid
4093
4124
// missing block connections between end of rescan and validation subscribing.
4094
4125
// Because of wallet lock being hold, block connection notifications are going to
@@ -4122,21 +4153,21 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
4122
4153
4123
4154
if (tip_height && *tip_height != rescan_height)
4124
4155
{
4125
- // We can't rescan beyond non-pruned blocks, stop and throw an error.
4126
- // This might happen if a user uses an old wallet within a pruned node
4127
- // or if they ran -disablewallet for a longer time, then decided to re-enable
4128
4156
if (chain.havePruned ()) {
4129
- // Exit early and print an error.
4130
- // If a block is pruned after this check, we will load the wallet,
4131
- // but fail the rescan with a generic error.
4132
4157
int block_height = *tip_height;
4133
4158
while (block_height > 0 && chain.haveBlockOnDisk (block_height - 1 ) && rescan_height != block_height) {
4134
4159
--block_height;
4135
4160
}
4136
4161
4137
4162
if (rescan_height != block_height) {
4163
+ // We can't rescan beyond non-pruned blocks, stop and throw an error.
4164
+ // This might happen if a user uses an old wallet within a pruned node
4165
+ // or if they ran -disablewallet for a longer time, then decided to re-enable
4166
+ // Exit early and print an error.
4167
+ // If a block is pruned after this check, we will load the wallet,
4168
+ // but fail the rescan with a generic error.
4138
4169
error = _ (" Prune: last wallet synchronisation goes beyond pruned data. You need to -reindex (download the whole blockchain again in case of pruned node)" );
4139
- return nullptr ;
4170
+ return false ;
4140
4171
}
4141
4172
}
4142
4173
@@ -4158,29 +4189,14 @@ std::shared_ptr<CWallet> CWallet::Create(interfaces::Chain& chain, const std::st
4158
4189
WalletRescanReserver reserver (*walletInstance);
4159
4190
if (!reserver.reserve () || (ScanResult::SUCCESS != walletInstance->ScanForWalletTransactions (chain.getBlockHash (rescan_height), rescan_height, {} /* max height */ , reserver, true /* update */ ).status )) {
4160
4191
error = _ (" Failed to rescan the wallet during initialization" );
4161
- return nullptr ;
4192
+ return false ;
4162
4193
}
4163
4194
}
4164
4195
walletInstance->chainStateFlushed (chain.getTipLocator ());
4165
4196
walletInstance->GetDatabase ().IncrementUpdateCounter ();
4166
4197
}
4167
4198
4168
- {
4169
- LOCK (cs_wallets);
4170
- for (auto & load_wallet : g_load_wallet_fns) {
4171
- load_wallet (interfaces::MakeWallet (walletInstance));
4172
- }
4173
- }
4174
-
4175
- walletInstance->SetBroadcastTransactions (gArgs .GetBoolArg (" -walletbroadcast" , DEFAULT_WALLETBROADCAST));
4176
-
4177
- {
4178
- walletInstance->WalletLogPrintf (" setKeyPool.size() = %u\n " , walletInstance->GetKeyPoolSize ());
4179
- walletInstance->WalletLogPrintf (" mapWallet.size() = %u\n " , walletInstance->mapWallet .size ());
4180
- walletInstance->WalletLogPrintf (" m_address_book.size() = %u\n " , walletInstance->m_address_book .size ());
4181
- }
4182
-
4183
- return walletInstance;
4199
+ return true ;
4184
4200
}
4185
4201
4186
4202
const CAddressBookData* CWallet::FindAddressBookEntry (const CTxDestination& dest, bool allow_change) const
0 commit comments