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 0bfc890af7
commit 98f362d6cc
4 changed files with 38 additions and 14 deletions

View File

@ -501,7 +501,6 @@ public:
/* 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);

View File

@ -3604,6 +3604,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();
@ -3620,13 +3630,26 @@ void CWallet::AddScriptPubKeyMan(const uint256& id, std::unique_ptr<ScriptPubKey
MaybeUpdateBirthTime(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();
@ -3994,7 +4017,7 @@ std::optional<MigrationData> CWallet::GetDescriptorsForLegacy(bilingual_str& err
{
AssertLockHeld(cs_wallet);
LegacyScriptPubKeyMan* legacy_spkm = GetLegacyScriptPubKeyMan();
LegacyDataSPKM* legacy_spkm = GetLegacyDataSPKM();
if (!Assume(legacy_spkm)) {
// This shouldn't happen
error = Untranslated(STR_INTERNAL_BUG("Error: Legacy wallet data missing"));
@ -4013,7 +4036,7 @@ bool CWallet::ApplyMigrationData(MigrationData& data, bilingual_str& error)
{
AssertLockHeld(cs_wallet);
LegacyScriptPubKeyMan* legacy_spkm = GetLegacyScriptPubKeyMan();
LegacyDataSPKM* legacy_spkm = GetLegacyDataSPKM();
if (!Assume(legacy_spkm)) {
// This shouldn't happen
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.
LegacyScriptPubKeyMan* GetLegacyScriptPubKeyMan() const;
LegacyScriptPubKeyMan* GetOrCreateLegacyScriptPubKeyMan();
LegacyDataSPKM* GetLegacyDataSPKM() const;
LegacyDataSPKM* GetOrCreateLegacyDataSPKM();
//! Make a LegacyScriptPubKeyMan and set it for all types, internal, and external.
void SetupLegacyScriptPubKeyMan();

View File

@ -356,7 +356,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;
@ -395,7 +395,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;
@ -442,7 +442,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();
@ -586,7 +586,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;
@ -609,7 +609,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) {
@ -676,7 +676,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) {
@ -697,7 +697,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;
});
@ -710,7 +710,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);
@ -722,7 +722,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);
@ -765,7 +765,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);