diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4697a90d6..197e50d9b 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1136,6 +1136,32 @@ bool CWallet::LoadCaches() } } + // Sapling legacy addresses were not directly added to the keystore; instead, + // the default address for each key was automatically added to the in-memory + // keystore, but not persisted. Following the addition of unified addresses, + // all addresses must be written to the wallet database explicitly. + auto legacySeed = GetLegacyHDSeed(); + if (legacySeed.has_value()) { + for (const auto& [saplingIvk, keyMeta] : mapSaplingZKeyMetadata) { + // This condition only applies for keys derived from the legacy seed + if (keyMeta.seedFp == legacySeed.value().Fingerprint()) { + SaplingExtendedFullViewingKey extfvk; + if (GetSaplingFullViewingKey(saplingIvk, extfvk)) { + auto defaultAddress = extfvk.DefaultAddress(); + if (!HaveSaplingIncomingViewingKey(defaultAddress)) { + // restore the address to the keystore and persist it so that + // the database state is consistent. + if (!AddSaplingPaymentAddress(saplingIvk, defaultAddress)) { + LogPrintf("%s: Error: Failed to write legacy Sapling payment address to the wallet database.\n", + __func__); + return false; + } + } + } + } + } + } + // Restore decrypted Orchard notes. for (const auto& [_, walletTx] : mapWallet) { if (!walletTx.orchardTxMeta.empty()) {