Skip to content

Commit

Permalink
wallet: Use LegacyDataSPKM when loading
Browse files Browse the repository at this point in the history
In SetupLegacyScriptPubKeyMan, a base LegacyDataSPKM will be created if
the database has the format "bdb_ro" (i.e. the wallet was opened only
for migration purposes).

All of the loading functions are now called with a LegacyDataSPKM object
instead of LegacyScriptPubKeyMan.
  • Loading branch information
achow101 committed Sep 27, 2023
1 parent e40bc1b commit 1b865df
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 16 deletions.
1 change: 0 additions & 1 deletion src/wallet/scriptpubkeyman.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,7 +498,6 @@ class LegacyScriptPubKeyMan : public LegacyDataSPKM

/* Set the HD chain model (chain child index counters) and writes it to the database */
void AddHDChain(const CHDChain& chain);
const CHDChain& GetHDChain() const { return m_hd_chain; }

//! Remove a watch only script from the keystore
bool RemoveWatchOnly(const CScript &dest);
Expand Down
33 changes: 28 additions & 5 deletions src/wallet/wallet.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3479,6 +3479,16 @@ LegacyScriptPubKeyMan* CWallet::GetLegacyScriptPubKeyMan() const
return dynamic_cast<LegacyScriptPubKeyMan*>(it->second);
}

LegacyDataSPKM* CWallet::GetLegacyDataSPKM() const
{
if (IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
return nullptr;
}
auto it = m_internal_spk_managers.find(OutputType::LEGACY);
if (it == m_internal_spk_managers.end()) return nullptr;
return dynamic_cast<LegacyDataSPKM*>(it->second);
}

LegacyScriptPubKeyMan* CWallet::GetOrCreateLegacyScriptPubKeyMan()
{
SetupLegacyScriptPubKeyMan();
Expand All @@ -3493,13 +3503,26 @@ void CWallet::AddScriptPubKeyMan(const uint256& id, std::unique_ptr<ScriptPubKey
FirstKeyTimeChanged(spkm.get(), spkm->GetTimeFirstKey());
}

LegacyDataSPKM* CWallet::GetOrCreateLegacyDataSPKM()
{
SetupLegacyScriptPubKeyMan();
return GetLegacyDataSPKM();
}

void CWallet::SetupLegacyScriptPubKeyMan()
{
if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() || !m_spk_managers.empty() || IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
return;
}

auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new LegacyScriptPubKeyMan(*this, m_keypool_size));
std::unique_ptr<ScriptPubKeyMan> spk_manager;

// Only create base LegacyDataSPKM if using BERKELEY_RO
if (m_database->Format() == "bdb_ro") {
spk_manager = std::unique_ptr<ScriptPubKeyMan>(new LegacyDataSPKM(*this));
} else {
spk_manager = std::unique_ptr<ScriptPubKeyMan>(new LegacyScriptPubKeyMan(*this, m_keypool_size));
}
for (const auto& type : LEGACY_OUTPUT_TYPES) {
m_internal_spk_managers[type] = spk_manager.get();
m_external_spk_managers[type] = spk_manager.get();
Expand Down Expand Up @@ -3839,7 +3862,7 @@ std::optional<MigrationData> CWallet::GetDescriptorsForLegacy(bilingual_str& err
{
AssertLockHeld(cs_wallet);

LegacyScriptPubKeyMan* legacy_spkm = GetLegacyScriptPubKeyMan();
LegacyDataSPKM* legacy_spkm = GetLegacyDataSPKM();
assert(legacy_spkm);

std::optional<MigrationData> res = legacy_spkm->MigrateToDescriptor();
Expand All @@ -3854,7 +3877,7 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
{
AssertLockHeld(cs_wallet);

LegacyScriptPubKeyMan* legacy_spkm = GetLegacyScriptPubKeyMan();
LegacyDataSPKM* legacy_spkm = GetLegacyDataSPKM();
if (!legacy_spkm) {
error = _("Error: This wallet is already a descriptor wallet");
return false;
Expand Down Expand Up @@ -4147,7 +4170,7 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle

// If the wallet is still loaded, unload it so that nothing else tries to use it while we're changing it
if (auto wallet = GetWallet(context, wallet_name)) {
if (!wallet->GetLegacyScriptPubKeyMan()) {
if (!wallet->GetLegacyDataSPKM()) {
return util::Error{_("Error: This wallet is already a descriptor wallet")};
}

Expand All @@ -4172,7 +4195,7 @@ util::Result<MigrationResult> MigrateLegacyToDescriptor(const std::string& walle
return util::Error{Untranslated("Wallet loading failed.") + Untranslated(" ") + error};
}

if (!wallet->GetLegacyScriptPubKeyMan()) {
if (!wallet->GetLegacyDataSPKM()) {
return util::Error{_("Error: This wallet is already a descriptor wallet")};
}
// Unload
Expand Down
2 changes: 2 additions & 0 deletions src/wallet/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -945,6 +945,8 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
//! Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
LegacyScriptPubKeyMan* GetLegacyScriptPubKeyMan() const;
LegacyScriptPubKeyMan* GetOrCreateLegacyScriptPubKeyMan();
LegacyDataSPKM* GetLegacyDataSPKM() const;
LegacyDataSPKM* GetOrCreateLegacyDataSPKM();

//! Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
void SetupLegacyScriptPubKeyMan();
Expand Down
20 changes: 10 additions & 10 deletions src/wallet/walletdb.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,7 @@ bool LoadKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::stri
strErr = "Error reading wallet database: CPrivKey corrupt";
return false;
}
if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKey(key, vchPubKey))
if (!pwallet->GetOrCreateLegacyDataSPKM()->LoadKey(key, vchPubKey))
{
strErr = "Error reading wallet database: LegacyScriptPubKeyMan::LoadKey failed";
return false;
Expand Down Expand Up @@ -391,7 +391,7 @@ bool LoadCryptedKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, st
}
}

if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadCryptedKey(vchPubKey, vchPrivKey, checksum_valid))
if (!pwallet->GetOrCreateLegacyDataSPKM()->LoadCryptedKey(vchPubKey, vchPrivKey, checksum_valid))
{
strErr = "Error reading wallet database: LegacyScriptPubKeyMan::LoadCryptedKey failed";
return false;
Expand Down Expand Up @@ -438,7 +438,7 @@ bool LoadHDChain(CWallet* pwallet, DataStream& ssValue, std::string& strErr)
try {
CHDChain chain;
ssValue >> chain;
pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadHDChain(chain);
pwallet->GetOrCreateLegacyDataSPKM()->LoadHDChain(chain);
} catch (const std::exception& e) {
if (strErr.empty()) {
strErr = e.what();
Expand Down Expand Up @@ -582,7 +582,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
key >> hash;
CScript script;
value >> script;
if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadCScript(script))
if (!pwallet->GetOrCreateLegacyDataSPKM()->LoadCScript(script))
{
strErr = "Error reading wallet database: LegacyScriptPubKeyMan::LoadCScript failed";
return DBErrors::NONCRITICAL_ERROR;
Expand All @@ -605,7 +605,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
key >> vchPubKey;
CKeyMetadata keyMeta;
value >> keyMeta;
pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKeyMetadata(vchPubKey.GetID(), keyMeta);
pwallet->GetOrCreateLegacyDataSPKM()->LoadKeyMetadata(vchPubKey.GetID(), keyMeta);

// Extract some CHDChain info from this metadata if it has any
if (keyMeta.nVersion >= CKeyMetadata::VERSION_WITH_HDDATA && !keyMeta.hd_seed_id.IsNull() && keyMeta.hdKeypath.size() > 0) {
Expand Down Expand Up @@ -672,7 +672,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,

// Set inactive chains
if (!hd_chains.empty()) {
LegacyScriptPubKeyMan* legacy_spkm = pwallet->GetLegacyScriptPubKeyMan();
LegacyDataSPKM* legacy_spkm = pwallet->GetLegacyDataSPKM();
if (legacy_spkm) {
for (const auto& [hd_seed_id, chain] : hd_chains) {
if (hd_seed_id != legacy_spkm->GetHDChain().seed_id) {
Expand All @@ -693,7 +693,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
uint8_t fYes;
value >> fYes;
if (fYes == '1') {
pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadWatchOnly(script);
pwallet->GetOrCreateLegacyDataSPKM()->LoadWatchOnly(script);
}
return DBErrors::LOAD_OK;
});
Expand All @@ -706,7 +706,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
key >> script;
CKeyMetadata keyMeta;
value >> keyMeta;
pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadScriptMetadata(CScriptID(script), keyMeta);
pwallet->GetOrCreateLegacyDataSPKM()->LoadScriptMetadata(CScriptID(script), keyMeta);
return DBErrors::LOAD_OK;
});
result = std::max(result, watch_meta_res.m_result);
Expand All @@ -718,7 +718,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
key >> nIndex;
CKeyPool keypool;
value >> keypool;
pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKeyPool(nIndex, keypool);
pwallet->GetOrCreateLegacyDataSPKM()->LoadKeyPool(nIndex, keypool);
return DBErrors::LOAD_OK;
});
result = std::max(result, pool_res.m_result);
Expand Down Expand Up @@ -761,7 +761,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,

// nTimeFirstKey is only reliable if all keys have metadata
if (pwallet->IsLegacy() && (key_res.m_records + ckey_res.m_records + watch_script_res.m_records) != (keymeta_res.m_records + watch_meta_res.m_records)) {
auto spk_man = pwallet->GetOrCreateLegacyScriptPubKeyMan();
auto spk_man = pwallet->GetLegacyScriptPubKeyMan();
if (spk_man) {
LOCK(spk_man->cs_KeyStore);
spk_man->UpdateTimeFirstKey(1);
Expand Down

0 comments on commit 1b865df

Please sign in to comment.