@@ -168,6 +168,7 @@ const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
168168CPubKey CWallet::GenerateNewKey (WalletBatch &batch, bool internal)
169169{
170170 assert (!IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS));
171+ assert (!IsWalletFlagSet (WALLET_FLAG_BLANK_WALLET));
171172 AssertLockHeld (cs_wallet); // mapKeyMetadata
172173 bool fCompressed = CanSupportFeature (FEATURE_COMPRPUBKEY); // default to compressed public keys if we want 0.6.0 wallets
173174
@@ -177,7 +178,7 @@ CPubKey CWallet::GenerateNewKey(WalletBatch &batch, bool internal)
177178 int64_t nCreationTime = GetTime ();
178179 CKeyMetadata metadata (nCreationTime);
179180
180- // use HD key derivation if HD was enabled during wallet creation
181+ // use HD key derivation if HD was enabled during wallet creation and a seed is present
181182 if (IsHDEnabled ()) {
182183 DeriveNewChildKey (batch, metadata, secret, (CanSupportFeature (FEATURE_HD_SPLIT) ? internal : false ));
183184 } else {
@@ -283,6 +284,7 @@ bool CWallet::AddKeyPubKeyWithDB(WalletBatch &batch, const CKey& secret, const C
283284 secret.GetPrivKey (),
284285 mapKeyMetadata[pubkey.GetID ()]);
285286 }
287+ UnsetWalletFlag (WALLET_FLAG_BLANK_WALLET);
286288 return true ;
287289}
288290
@@ -349,7 +351,11 @@ bool CWallet::AddCScript(const CScript& redeemScript)
349351{
350352 if (!CCryptoKeyStore::AddCScript (redeemScript))
351353 return false ;
352- return WalletBatch (*database).WriteCScript (Hash160 (redeemScript), redeemScript);
354+ if (WalletBatch (*database).WriteCScript (Hash160 (redeemScript), redeemScript)) {
355+ UnsetWalletFlag (WALLET_FLAG_BLANK_WALLET);
356+ return true ;
357+ }
358+ return false ;
353359}
354360
355361bool CWallet::LoadCScript (const CScript& redeemScript)
@@ -374,7 +380,11 @@ bool CWallet::AddWatchOnly(const CScript& dest)
374380 const CKeyMetadata& meta = m_script_metadata[CScriptID (dest)];
375381 UpdateTimeFirstKey (meta.nCreateTime );
376382 NotifyWatchonlyChanged (true );
377- return WalletBatch (*database).WriteWatchOnly (dest, meta);
383+ if (WalletBatch (*database).WriteWatchOnly (dest, meta)) {
384+ UnsetWalletFlag (WALLET_FLAG_BLANK_WALLET);
385+ return true ;
386+ }
387+ return false ;
378388}
379389
380390bool CWallet::AddWatchOnly (const CScript& dest, int64_t nCreateTime)
@@ -1402,6 +1412,7 @@ void CWallet::SetHDSeed(const CPubKey& seed)
14021412 newHdChain.seed_id = seed.GetID ();
14031413 SetHDChain (newHdChain, false );
14041414 NotifyCanGetAddressesChanged ();
1415+ UnsetWalletFlag (WALLET_FLAG_BLANK_WALLET);
14051416}
14061417
14071418void CWallet::SetHDChain (const CHDChain& chain, bool memonly)
@@ -1418,6 +1429,30 @@ bool CWallet::IsHDEnabled() const
14181429 return !hdChain.seed_id .IsNull ();
14191430}
14201431
1432+ bool CWallet::CanGenerateKeys ()
1433+ {
1434+ // A wallet can generate keys if it has an HD seed (IsHDEnabled) or it is a non-HD wallet (pre FEATURE_HD)
1435+ LOCK (cs_wallet);
1436+ return IsHDEnabled () || !CanSupportFeature (FEATURE_HD);
1437+ }
1438+
1439+ bool CWallet::CanGetAddresses (bool internal)
1440+ {
1441+ LOCK (cs_wallet);
1442+ // Check if the keypool has keys
1443+ bool keypool_has_keys;
1444+ if (internal && CanSupportFeature (FEATURE_HD_SPLIT)) {
1445+ keypool_has_keys = setInternalKeyPool.size () > 0 ;
1446+ } else {
1447+ keypool_has_keys = KeypoolCountExternalKeys () > 0 ;
1448+ }
1449+ // If the keypool doesn't have keys, check if we can generate them
1450+ if (!keypool_has_keys) {
1451+ return CanGenerateKeys ();
1452+ }
1453+ return keypool_has_keys;
1454+ }
1455+
14211456void CWallet::SetWalletFlag (uint64_t flags)
14221457{
14231458 LOCK (cs_wallet);
@@ -1426,6 +1461,14 @@ void CWallet::SetWalletFlag(uint64_t flags)
14261461 throw std::runtime_error (std::string (__func__) + " : writing wallet flags failed" );
14271462}
14281463
1464+ void CWallet::UnsetWalletFlag (uint64_t flag)
1465+ {
1466+ LOCK (cs_wallet);
1467+ m_wallet_flags &= ~flag;
1468+ if (!WalletBatch (*database).WriteWalletFlags (m_wallet_flags))
1469+ throw std::runtime_error (std::string (__func__) + " : writing wallet flags failed" );
1470+ }
1471+
14291472bool CWallet::IsWalletFlagSet (uint64_t flag)
14301473{
14311474 return (m_wallet_flags & flag);
@@ -3101,7 +3144,8 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
31013144 {
31023145 LOCK (cs_KeyStore);
31033146 // This wallet is in its first run if all of these are empty
3104- fFirstRunRet = mapKeys.empty () && mapCryptedKeys.empty () && mapWatchKeys.empty () && setWatchOnly.empty () && mapScripts.empty () && !IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS);
3147+ fFirstRunRet = mapKeys.empty () && mapCryptedKeys.empty () && mapWatchKeys.empty () && setWatchOnly.empty () && mapScripts.empty ()
3148+ && !IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS) && !IsWalletFlagSet (WALLET_FLAG_BLANK_WALLET);
31053149 }
31063150
31073151 if (nLoadWalletRet != DBErrors::LOAD_OK)
@@ -3286,7 +3330,7 @@ void CWallet::LoadKeyPool(int64_t nIndex, const CKeyPool &keypool)
32863330
32873331bool CWallet::TopUpKeyPool (unsigned int kpSize)
32883332{
3289- if (IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS )) {
3333+ if (! CanGenerateKeys ( )) {
32903334 return false ;
32913335 }
32923336 {
@@ -3416,7 +3460,7 @@ void CWallet::ReturnKey(int64_t nIndex, bool fInternal, const CPubKey& pubkey)
34163460
34173461bool CWallet::GetKeyFromPool (CPubKey& result, bool internal)
34183462{
3419- if (IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS )) {
3463+ if (! CanGetAddresses (internal )) {
34203464 return false ;
34213465 }
34223466
@@ -3617,6 +3661,10 @@ std::set<CTxDestination> CWallet::GetLabelAddresses(const std::string& label) co
36173661
36183662bool CReserveKey::GetReservedKey (CPubKey& pubkey, bool internal)
36193663{
3664+ if (!pwallet->CanGetAddresses (internal)) {
3665+ return false ;
3666+ }
3667+
36203668 if (nIndex == -1 )
36213669 {
36223670 CKeyPool keypool;
@@ -4071,14 +4119,16 @@ std::shared_ptr<CWallet> CWallet::CreateWalletFromFile(interfaces::Chain& chain,
40714119 if ((wallet_creation_flags & WALLET_FLAG_DISABLE_PRIVATE_KEYS)) {
40724120 // selective allow to set flags
40734121 walletInstance->SetWalletFlag (WALLET_FLAG_DISABLE_PRIVATE_KEYS);
4122+ } else if (wallet_creation_flags & WALLET_FLAG_BLANK_WALLET) {
4123+ walletInstance->SetWalletFlag (WALLET_FLAG_BLANK_WALLET);
40744124 } else {
40754125 // generate a new seed
40764126 CPubKey seed = walletInstance->GenerateNewSeed ();
40774127 walletInstance->SetHDSeed (seed);
4078- }
4128+ } // Otherwise, do not generate a new seed
40794129
40804130 // Top up the keypool
4081- if (! walletInstance->IsWalletFlagSet (WALLET_FLAG_DISABLE_PRIVATE_KEYS ) && !walletInstance->TopUpKeyPool ()) {
4131+ if (walletInstance->CanGenerateKeys ( ) && !walletInstance->TopUpKeyPool ()) {
40824132 InitError (_ (" Unable to generate initial keys" ));
40834133 return nullptr ;
40844134 }
0 commit comments