Skip to content

Commit bbc9e41

Browse files
committed
Merge #17304: refactor: Move many functions into LegacyScriptPubKeyMan and further separate it from CWallet
152b0a0 Refactor: Move nTimeFirstKey accesses out of CWallet (Andrew Chow) 7ef47b8 Refactor: Move GetKeypoolSize code out of CWallet (Andrew Chow) 089e17d Refactor: Move RewriteDB code out of CWallet (Andrew Chow) 0eac708 Refactor: Move SetupGeneration code out of CWallet (Andrew Chow) f45d12b Refactor: Move HavePrivateKeys code out of CWallet::CreateWalletFromFile (Andrew Chow) 8b0d82b Refactor: Move Upgrade code out of CWallet::CreateWalletFromFile (Andrew Chow) 46865ec Refactor: Move MarkUnusedAddresses code out of CWallet::AddToWalletIfInvolvingMe (Andrew Chow) a18edd7 Refactor: Move GetMetadata code out of getaddressinfo (Andrew Chow) 9716bbe Refactor: Move LoadKey LegacyScriptPubKeyMan method definition (Andrew Chow) 67be6b9 Refactor: Move SetAddressBookWithDB call out of LegacyScriptPubKeyMan::ImportScriptPubKeys (Andrew Chow) fc2867f refactor: Replace UnsetWalletFlagWithDB with UnsetBlankWalletFlag in ScriptPubKeyMan (Andrew Chow) 78e7cbc Refactor: Remove UnsetWalletFlag call from LegacyScriptPubKeyMan::SetHDSeed (Andrew Chow) 0391aba Remove SetWalletFlag from WalletStorage (Andrew Chow) 4c5491f Refactor: Move SetWalletFlag out of LegacyScriptPubKeyMan::UpgradeKeyMetadata (Andrew Chow) 769acef Refactor: Move SetAddressBook call out of LegacyScriptPubKeyMan::GetNewDestination (Andrew Chow) acedc5b Refactor: Add new ScriptPubKeyMan virtual methods (Andrew Chow) 533d8b3 Refactor: Declare LegacyScriptPubKeyMan methods as virtual (Andrew Chow) b4cb18b MOVEONLY: Reorder LegacyScriptPubKeyMan methods (Andrew Chow) Pull request description: Moves several more key management and metadata functions into LegacyScriptPubKeyMan from CWallet to further separate the two. Note to reviewers: All of the `if (auto spk_man = walletInstance->m_spk_man.get()) {` blocks will be replaced with for loops in the next PR so you may see some things in those blocks that don't necessarily make sense with an `if` but will with a `for`. ACKs for top commit: laanwj: code review ACK 152b0a0 Sjors: re-ACK 152b0a0 promag: Code review ACK 152b0a0. Tree-SHA512: ff9872a3ef818922166cb15d72363004ec184e1015a3928a66091bddf48995423602ccd7e55b814de85d25ad7c69058280b1fde2e633570c680dc7d6084b3122
2 parents fba574c + 152b0a0 commit bbc9e41

File tree

5 files changed

+415
-229
lines changed

5 files changed

+415
-229
lines changed

src/wallet/rpcwallet.cpp

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3756,26 +3756,24 @@ UniValue getaddressinfo(const JSONRPCRequest& request)
37563756
ret.pushKV("label", pwallet->mapAddressBook[dest].name);
37573757
}
37583758
ret.pushKV("ischange", pwallet->IsChange(scriptPubKey));
3759-
const CKeyMetadata* meta = nullptr;
3760-
CKeyID key_id = GetKeyForDestination(*provider, dest);
3761-
if (!key_id.IsNull()) {
3762-
auto it = pwallet->mapKeyMetadata.find(key_id);
3763-
if (it != pwallet->mapKeyMetadata.end()) {
3764-
meta = &it->second;
3759+
3760+
ScriptPubKeyMan* spk_man = pwallet->GetScriptPubKeyMan();
3761+
if (spk_man) {
3762+
CKeyID key_id = GetKeyForDestination(*provider, dest);
3763+
const CKeyMetadata* meta = nullptr;
3764+
if (!key_id.IsNull()) {
3765+
meta = spk_man->GetMetadata(key_id);
37653766
}
3766-
}
3767-
if (!meta) {
3768-
auto it = pwallet->m_script_metadata.find(CScriptID(scriptPubKey));
3769-
if (it != pwallet->m_script_metadata.end()) {
3770-
meta = &it->second;
3767+
if (!meta) {
3768+
meta = spk_man->GetMetadata(CScriptID(scriptPubKey));
37713769
}
3772-
}
3773-
if (meta) {
3774-
ret.pushKV("timestamp", meta->nCreateTime);
3775-
if (meta->has_key_origin) {
3776-
ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path));
3777-
ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
3778-
ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint, meta->key_origin.fingerprint + 4));
3770+
if (meta) {
3771+
ret.pushKV("timestamp", meta->nCreateTime);
3772+
if (meta->has_key_origin) {
3773+
ret.pushKV("hdkeypath", WriteHDKeypath(meta->key_origin.path));
3774+
ret.pushKV("hdseedid", meta->hd_seed_id.GetHex());
3775+
ret.pushKV("hdmasterfingerprint", HexStr(meta->key_origin.fingerprint, meta->key_origin.fingerprint + 4));
3776+
}
37793777
}
37803778
}
37813779

src/wallet/scriptpubkeyman.cpp

Lines changed: 146 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,8 @@
1111
#include <wallet/scriptpubkeyman.h>
1212
#include <wallet/wallet.h>
1313

14-
bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, const std::string label, CTxDestination& dest, std::string& error)
14+
bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, CTxDestination& dest, std::string& error)
1515
{
16-
LOCK(cs_wallet);
1716
error.clear();
1817
TopUpKeyPool();
1918

@@ -25,8 +24,6 @@ bool LegacyScriptPubKeyMan::GetNewDestination(const OutputType type, const std::
2524
}
2625
LearnRelatedScripts(new_key, type);
2726
dest = GetDestinationForKey(new_key, type);
28-
29-
m_wallet.SetAddressBook(dest, label, "receive");
3027
return true;
3128
}
3229

@@ -265,6 +262,48 @@ bool LegacyScriptPubKeyMan::EncryptKeys(CKeyingMaterial& vMasterKeyIn)
265262
return true;
266263
}
267264

265+
bool LegacyScriptPubKeyMan::GetReservedDestination(const OutputType type, bool internal, int64_t& index, CKeyPool& keypool)
266+
{
267+
{
268+
if (!ReserveKeyFromKeyPool(index, keypool, internal)) {
269+
return false;
270+
}
271+
}
272+
return true;
273+
}
274+
275+
void LegacyScriptPubKeyMan::KeepDestination(int64_t index)
276+
{
277+
KeepKey(index);
278+
}
279+
280+
void LegacyScriptPubKeyMan::ReturnDestination(int64_t index, bool internal, const CPubKey& pubkey)
281+
{
282+
ReturnKey(index, internal, pubkey);
283+
}
284+
285+
bool LegacyScriptPubKeyMan::TopUp(unsigned int size)
286+
{
287+
return TopUpKeyPool(size);
288+
}
289+
290+
void LegacyScriptPubKeyMan::MarkUnusedAddresses(const CScript& script)
291+
{
292+
AssertLockHeld(cs_wallet);
293+
// extract addresses and check if they match with an unused keypool key
294+
for (const auto& keyid : GetAffectedKeys(script, *this)) {
295+
std::map<CKeyID, int64_t>::const_iterator mi = m_pool_key_to_index.find(keyid);
296+
if (mi != m_pool_key_to_index.end()) {
297+
WalletLogPrintf("%s: Detected a used keypool key, mark all keypool key up to this key as used\n", __func__);
298+
MarkReserveKeysAsUsed(mi->second);
299+
300+
if (!TopUpKeyPool()) {
301+
WalletLogPrintf("%s: Topping up keypool failed (locked wallet)\n", __func__);
302+
}
303+
}
304+
}
305+
}
306+
268307
void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
269308
{
270309
AssertLockHeld(cs_wallet);
@@ -298,8 +337,19 @@ void LegacyScriptPubKeyMan::UpgradeKeyMetadata()
298337
}
299338
}
300339
}
301-
batch.reset(); //write before setting the flag
302-
m_storage.SetWalletFlag(WALLET_FLAG_KEY_ORIGIN_METADATA);
340+
}
341+
342+
bool LegacyScriptPubKeyMan::SetupGeneration(bool force)
343+
{
344+
if ((CanGenerateKeys() && !force) || m_storage.IsLocked()) {
345+
return false;
346+
}
347+
348+
SetHDSeed(GenerateNewSeed());
349+
if (!NewKeyPool()) {
350+
return false;
351+
}
352+
return true;
303353
}
304354

305355
bool LegacyScriptPubKeyMan::IsHDEnabled() const
@@ -324,6 +374,58 @@ bool LegacyScriptPubKeyMan::CanGetAddresses(bool internal)
324374
return keypool_has_keys;
325375
}
326376

377+
bool LegacyScriptPubKeyMan::Upgrade(int prev_version, std::string& error)
378+
{
379+
AssertLockHeld(cs_wallet);
380+
error = "";
381+
bool hd_upgrade = false;
382+
bool split_upgrade = false;
383+
if (m_storage.CanSupportFeature(FEATURE_HD) && !IsHDEnabled()) {
384+
WalletLogPrintf("Upgrading wallet to HD\n");
385+
m_storage.SetMinVersion(FEATURE_HD);
386+
387+
// generate a new master key
388+
CPubKey masterPubKey = GenerateNewSeed();
389+
SetHDSeed(masterPubKey);
390+
hd_upgrade = true;
391+
}
392+
// Upgrade to HD chain split if necessary
393+
if (m_storage.CanSupportFeature(FEATURE_HD_SPLIT)) {
394+
WalletLogPrintf("Upgrading wallet to use HD chain split\n");
395+
m_storage.SetMinVersion(FEATURE_PRE_SPLIT_KEYPOOL);
396+
split_upgrade = FEATURE_HD_SPLIT > prev_version;
397+
}
398+
// Mark all keys currently in the keypool as pre-split
399+
if (split_upgrade) {
400+
MarkPreSplitKeys();
401+
}
402+
// Regenerate the keypool if upgraded to HD
403+
if (hd_upgrade) {
404+
if (!TopUpKeyPool()) {
405+
error = _("Unable to generate keys").translated;
406+
return false;
407+
}
408+
}
409+
return true;
410+
}
411+
412+
bool LegacyScriptPubKeyMan::HavePrivateKeys() const
413+
{
414+
LOCK(cs_KeyStore);
415+
return !mapKeys.empty() || !mapCryptedKeys.empty();
416+
}
417+
418+
void LegacyScriptPubKeyMan::RewriteDB()
419+
{
420+
AssertLockHeld(cs_wallet);
421+
setInternalKeyPool.clear();
422+
setExternalKeyPool.clear();
423+
m_pool_key_to_index.clear();
424+
// Note: can't top-up keypool here, because wallet is locked.
425+
// User will be prompted to unlock wallet the next operation
426+
// that requires a new key.
427+
}
428+
327429
static int64_t GetOldestKeyTimeInPool(const std::set<int64_t>& setKeyPool, WalletBatch& batch) {
328430
if (setKeyPool.empty()) {
329431
return GetTime();
@@ -362,6 +464,33 @@ size_t LegacyScriptPubKeyMan::KeypoolCountExternalKeys()
362464
return setExternalKeyPool.size() + set_pre_split_keypool.size();
363465
}
364466

467+
unsigned int LegacyScriptPubKeyMan::GetKeyPoolSize() const
468+
{
469+
AssertLockHeld(cs_wallet);
470+
return setInternalKeyPool.size() + setExternalKeyPool.size();
471+
}
472+
473+
int64_t LegacyScriptPubKeyMan::GetTimeFirstKey() const
474+
{
475+
AssertLockHeld(cs_wallet);
476+
return nTimeFirstKey;
477+
}
478+
479+
const CKeyMetadata* LegacyScriptPubKeyMan::GetMetadata(uint160 id) const
480+
{
481+
AssertLockHeld(cs_wallet);
482+
auto it = mapKeyMetadata.find(CKeyID(id));
483+
if (it != mapKeyMetadata.end()) {
484+
return &it->second;
485+
} else {
486+
auto it2 = m_script_metadata.find(CScriptID(id));
487+
if (it2 != m_script_metadata.end()) {
488+
return &it2->second;
489+
}
490+
}
491+
return nullptr;
492+
}
493+
365494
/**
366495
* Update wallet first key creation time. This should be called whenever keys
367496
* are added to the wallet, with the oldest key creation time.
@@ -378,6 +507,11 @@ void LegacyScriptPubKeyMan::UpdateTimeFirstKey(int64_t nCreateTime)
378507
}
379508
}
380509

510+
bool LegacyScriptPubKeyMan::LoadKey(const CKey& key, const CPubKey &pubkey)
511+
{
512+
return AddKeyPubKeyInner(key, pubkey);
513+
}
514+
381515
bool LegacyScriptPubKeyMan::AddKeyPubKey(const CKey& secret, const CPubKey &pubkey)
382516
{
383517
WalletBatch batch(m_storage.GetDatabase());
@@ -420,7 +554,7 @@ bool LegacyScriptPubKeyMan::AddKeyPubKeyWithDB(WalletBatch& batch, const CKey& s
420554
secret.GetPrivKey(),
421555
mapKeyMetadata[pubkey.GetID()]);
422556
}
423-
m_storage.UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
557+
m_storage.UnsetBlankWalletFlag(batch);
424558
return true;
425559
}
426560

@@ -577,7 +711,7 @@ bool LegacyScriptPubKeyMan::AddWatchOnlyWithDB(WalletBatch &batch, const CScript
577711
UpdateTimeFirstKey(meta.nCreateTime);
578712
NotifyWatchonlyChanged(true);
579713
if (batch.WriteWatchOnly(dest, meta)) {
580-
m_storage.UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
714+
m_storage.UnsetBlankWalletFlag(batch);
581715
return true;
582716
}
583717
return false;
@@ -855,7 +989,8 @@ void LegacyScriptPubKeyMan::SetHDSeed(const CPubKey& seed)
855989
newHdChain.seed_id = seed.GetID();
856990
SetHDChain(newHdChain, false);
857991
NotifyCanGetAddressesChanged();
858-
m_wallet.UnsetWalletFlag(WALLET_FLAG_BLANK_WALLET);
992+
WalletBatch batch(m_storage.GetDatabase());
993+
m_storage.UnsetBlankWalletFlag(batch);
859994
}
860995

861996
/**
@@ -1134,7 +1269,7 @@ bool LegacyScriptPubKeyMan::AddCScriptWithDB(WalletBatch& batch, const CScript&
11341269
if (!FillableSigningProvider::AddCScript(redeemScript))
11351270
return false;
11361271
if (batch.WriteCScript(Hash160(redeemScript), redeemScript)) {
1137-
m_storage.UnsetWalletFlagWithDB(batch, WALLET_FLAG_BLANK_WALLET);
1272+
m_storage.UnsetBlankWalletFlag(batch);
11381273
return true;
11391274
}
11401275
return false;
@@ -1229,7 +1364,7 @@ bool LegacyScriptPubKeyMan::ImportPubKeys(const std::vector<CKeyID>& ordered_pub
12291364
return true;
12301365
}
12311366

1232-
bool LegacyScriptPubKeyMan::ImportScriptPubKeys(const std::string& label, const std::set<CScript>& script_pub_keys, const bool have_solving_data, const bool apply_label, const int64_t timestamp)
1367+
bool LegacyScriptPubKeyMan::ImportScriptPubKeys(const std::set<CScript>& script_pub_keys, const bool have_solving_data, const int64_t timestamp)
12331368
{
12341369
WalletBatch batch(m_storage.GetDatabase());
12351370
for (const CScript& script : script_pub_keys) {
@@ -1238,11 +1373,6 @@ bool LegacyScriptPubKeyMan::ImportScriptPubKeys(const std::string& label, const
12381373
return false;
12391374
}
12401375
}
1241-
CTxDestination dest;
1242-
ExtractDestination(script, dest);
1243-
if (apply_label && IsValidDestination(dest)) {
1244-
m_wallet.SetAddressBookWithDB(batch, dest, label, "receive");
1245-
}
12461376
}
12471377
return true;
12481378
}

0 commit comments

Comments
 (0)