wallet: Use LegacyDataSPKM when loading

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.
This commit is contained in:
Ava Chow 2024-01-05 18:36:28 -05:00
parent 61d872f1b3
commit 771bc60f13
3 changed files with 34 additions and 13 deletions

View file

@ -3611,6 +3611,16 @@ LegacyScriptPubKeyMan* CWallet::GetLegacyScriptPubKeyMan() const
return dynamic_cast<LegacyScriptPubKeyMan*>(it->second); 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() LegacyScriptPubKeyMan* CWallet::GetOrCreateLegacyScriptPubKeyMan()
{ {
SetupLegacyScriptPubKeyMan(); SetupLegacyScriptPubKeyMan();
@ -3627,13 +3637,22 @@ void CWallet::AddScriptPubKeyMan(const uint256& id, std::unique_ptr<ScriptPubKey
MaybeUpdateBirthTime(spkm->GetTimeFirstKey()); MaybeUpdateBirthTime(spkm->GetTimeFirstKey());
} }
LegacyDataSPKM* CWallet::GetOrCreateLegacyDataSPKM()
{
SetupLegacyScriptPubKeyMan();
return GetLegacyDataSPKM();
}
void CWallet::SetupLegacyScriptPubKeyMan() void CWallet::SetupLegacyScriptPubKeyMan()
{ {
if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() || !m_spk_managers.empty() || IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) { if (!m_internal_spk_managers.empty() || !m_external_spk_managers.empty() || !m_spk_managers.empty() || IsWalletFlagSet(WALLET_FLAG_DESCRIPTORS)) {
return; return;
} }
auto spk_manager = std::unique_ptr<ScriptPubKeyMan>(new LegacyScriptPubKeyMan(*this, m_keypool_size)); std::unique_ptr<ScriptPubKeyMan> spk_manager = m_database->Format() == "bdb_ro" ?
std::make_unique<LegacyDataSPKM>(*this) :
std::make_unique<LegacyScriptPubKeyMan>(*this, m_keypool_size);
for (const auto& type : LEGACY_OUTPUT_TYPES) { for (const auto& type : LEGACY_OUTPUT_TYPES) {
m_internal_spk_managers[type] = spk_manager.get(); m_internal_spk_managers[type] = spk_manager.get();
m_external_spk_managers[type] = spk_manager.get(); m_external_spk_managers[type] = spk_manager.get();
@ -4001,7 +4020,7 @@ std::optional<MigrationData> CWallet::GetDescriptorsForLegacy(bilingual_str& err
{ {
AssertLockHeld(cs_wallet); AssertLockHeld(cs_wallet);
LegacyScriptPubKeyMan* legacy_spkm = GetLegacyScriptPubKeyMan(); LegacyDataSPKM* legacy_spkm = GetLegacyDataSPKM();
if (!Assume(legacy_spkm)) { if (!Assume(legacy_spkm)) {
// This shouldn't happen // This shouldn't happen
error = Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing")); error = Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"));
@ -4020,7 +4039,7 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
{ {
AssertLockHeld(cs_wallet); AssertLockHeld(cs_wallet);
LegacyScriptPubKeyMan* legacy_spkm = GetLegacyScriptPubKeyMan(); LegacyDataSPKM* legacy_spkm = GetLegacyDataSPKM();
if (!Assume(legacy_spkm)) { if (!Assume(legacy_spkm)) {
// This shouldn't happen // This shouldn't happen
error = Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing")); error = Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"));

View file

@ -961,6 +961,8 @@ public:
//! Get the LegacyScriptPubKeyMan which is used for all types, internal, and external. //! Get the LegacyScriptPubKeyMan which is used for all types, internal, and external.
LegacyScriptPubKeyMan* GetLegacyScriptPubKeyMan() const; LegacyScriptPubKeyMan* GetLegacyScriptPubKeyMan() const;
LegacyScriptPubKeyMan* GetOrCreateLegacyScriptPubKeyMan(); LegacyScriptPubKeyMan* GetOrCreateLegacyScriptPubKeyMan();
LegacyDataSPKM* GetLegacyDataSPKM() const;
LegacyDataSPKM* GetOrCreateLegacyDataSPKM();
//! Make a Legacy(Data)SPKM and set it for all types, internal, and external. //! Make a Legacy(Data)SPKM and set it for all types, internal, and external.
void SetupLegacyScriptPubKeyMan(); void SetupLegacyScriptPubKeyMan();

View file

@ -354,7 +354,7 @@ bool LoadKey(CWallet* pwallet, DataStream& ssKey, DataStream& ssValue, std::stri
strErr = "Error reading wallet database: CPrivKey corrupt"; strErr = "Error reading wallet database: CPrivKey corrupt";
return false; return false;
} }
if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKey(key, vchPubKey)) if (!pwallet->GetOrCreateLegacyDataSPKM()->LoadKey(key, vchPubKey))
{ {
strErr = "Error reading wallet database: LegacyDataSPKM::LoadKey failed"; strErr = "Error reading wallet database: LegacyDataSPKM::LoadKey failed";
return false; return false;
@ -393,7 +393,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: LegacyDataSPKM::LoadCryptedKey failed"; strErr = "Error reading wallet database: LegacyDataSPKM::LoadCryptedKey failed";
return false; return false;
@ -440,7 +440,7 @@ bool LoadHDChain(CWallet* pwallet, DataStream& ssValue, std::string& strErr)
try { try {
CHDChain chain; CHDChain chain;
ssValue >> chain; ssValue >> chain;
pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadHDChain(chain); pwallet->GetOrCreateLegacyDataSPKM()->LoadHDChain(chain);
} catch (const std::exception& e) { } catch (const std::exception& e) {
if (strErr.empty()) { if (strErr.empty()) {
strErr = e.what(); strErr = e.what();
@ -584,7 +584,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
key >> hash; key >> hash;
CScript script; CScript script;
value >> script; value >> script;
if (!pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadCScript(script)) if (!pwallet->GetOrCreateLegacyDataSPKM()->LoadCScript(script))
{ {
strErr = "Error reading wallet database: LegacyDataSPKM::LoadCScript failed"; strErr = "Error reading wallet database: LegacyDataSPKM::LoadCScript failed";
return DBErrors::NONCRITICAL_ERROR; return DBErrors::NONCRITICAL_ERROR;
@ -607,7 +607,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
key >> vchPubKey; key >> vchPubKey;
CKeyMetadata keyMeta; CKeyMetadata keyMeta;
value >> 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 // 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) { if (keyMeta.nVersion >= CKeyMetadata::VERSION_WITH_HDDATA && !keyMeta.hd_seed_id.IsNull() && keyMeta.hdKeypath.size() > 0) {
@ -674,7 +674,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
// Set inactive chains // Set inactive chains
if (!hd_chains.empty()) { if (!hd_chains.empty()) {
LegacyScriptPubKeyMan* legacy_spkm = pwallet->GetLegacyScriptPubKeyMan(); LegacyDataSPKM* legacy_spkm = pwallet->GetLegacyDataSPKM();
if (legacy_spkm) { if (legacy_spkm) {
for (const auto& [hd_seed_id, chain] : hd_chains) { for (const auto& [hd_seed_id, chain] : hd_chains) {
if (hd_seed_id != legacy_spkm->GetHDChain().seed_id) { if (hd_seed_id != legacy_spkm->GetHDChain().seed_id) {
@ -695,7 +695,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
uint8_t fYes; uint8_t fYes;
value >> fYes; value >> fYes;
if (fYes == '1') { if (fYes == '1') {
pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadWatchOnly(script); pwallet->GetOrCreateLegacyDataSPKM()->LoadWatchOnly(script);
} }
return DBErrors::LOAD_OK; return DBErrors::LOAD_OK;
}); });
@ -708,7 +708,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
key >> script; key >> script;
CKeyMetadata keyMeta; CKeyMetadata keyMeta;
value >> keyMeta; value >> keyMeta;
pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadScriptMetadata(CScriptID(script), keyMeta); pwallet->GetOrCreateLegacyDataSPKM()->LoadScriptMetadata(CScriptID(script), keyMeta);
return DBErrors::LOAD_OK; return DBErrors::LOAD_OK;
}); });
result = std::max(result, watch_meta_res.m_result); result = std::max(result, watch_meta_res.m_result);
@ -720,7 +720,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
key >> nIndex; key >> nIndex;
CKeyPool keypool; CKeyPool keypool;
value >> keypool; value >> keypool;
pwallet->GetOrCreateLegacyScriptPubKeyMan()->LoadKeyPool(nIndex, keypool); pwallet->GetOrCreateLegacyDataSPKM()->LoadKeyPool(nIndex, keypool);
return DBErrors::LOAD_OK; return DBErrors::LOAD_OK;
}); });
result = std::max(result, pool_res.m_result); result = std::max(result, pool_res.m_result);
@ -763,7 +763,7 @@ static DBErrors LoadLegacyWalletRecords(CWallet* pwallet, DatabaseBatch& batch,
// nTimeFirstKey is only reliable if all keys have metadata // 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)) { 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) { if (spk_man) {
LOCK(spk_man->cs_KeyStore); LOCK(spk_man->cs_KeyStore);
spk_man->UpdateTimeFirstKey(1); spk_man->UpdateTimeFirstKey(1);