diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index cef66fb46..c4be019c7 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -500,7 +500,7 @@ UniValue listaddresses(const UniValue& params, bool fHelp) UniValue sapling_obj(UniValue::VOBJ); - if (source == LegacyHDSeed || source == MnemonicHDSeed) { + if (source == PaymentAddressSource::LegacyHDSeed || source == PaymentAddressSource::MnemonicHDSeed) { std::string hdKeyPath = pwalletMain->mapSaplingZKeyMetadata[ivk].hdKeypath; if (hdKeyPath != "") { sapling_obj.pushKV("zip32KeyPath", hdKeyPath); @@ -531,7 +531,7 @@ UniValue listaddresses(const UniValue& params, bool fHelp) { UniValue imported_sprout_addrs(UniValue::VARR); for (const SproutPaymentAddress& addr : sproutAddresses) { - if (GetSourceForPaymentAddress(pwalletMain)(addr) == Imported) { + if (GetSourceForPaymentAddress(pwalletMain)(addr) == PaymentAddressSource::Imported) { imported_sprout_addrs.push_back(keyIO.EncodePaymentAddress(addr)); } } @@ -544,7 +544,7 @@ UniValue listaddresses(const UniValue& params, bool fHelp) } } - hasData |= add_sapling(saplingAddresses, Imported, entry); + hasData |= add_sapling(saplingAddresses, PaymentAddressSource::Imported, entry); if (hasData) { ret.push_back(entry); @@ -573,7 +573,7 @@ UniValue listaddresses(const UniValue& params, bool fHelp) { UniValue watchonly_sprout_addrs(UniValue::VARR); for (const SproutPaymentAddress& addr : sproutAddresses) { - if (GetSourceForPaymentAddress(pwalletMain)(addr) == ImportedWatchOnly) { + if (GetSourceForPaymentAddress(pwalletMain)(addr) == PaymentAddressSource::ImportedWatchOnly) { watchonly_sprout_addrs.push_back(keyIO.EncodePaymentAddress(addr)); } } @@ -586,7 +586,7 @@ UniValue listaddresses(const UniValue& params, bool fHelp) } } - hasData |= add_sapling(saplingAddresses, ImportedWatchOnly, entry); + hasData |= add_sapling(saplingAddresses, PaymentAddressSource::ImportedWatchOnly, entry); if (hasData) { ret.push_back(entry); @@ -598,7 +598,7 @@ UniValue listaddresses(const UniValue& params, bool fHelp) UniValue entry(UniValue::VOBJ); entry.pushKV("source", "legacy_hdseed"); - bool hasData = add_sapling(saplingAddresses, LegacyHDSeed, entry); + bool hasData = add_sapling(saplingAddresses, PaymentAddressSource::LegacyHDSeed, entry); if (hasData) { ret.push_back(entry); diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 4b1eec599..3cd82ab9f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -6193,63 +6193,119 @@ bool PaymentAddressBelongsToWallet::operator()(const libzcash::SproutPaymentAddr bool PaymentAddressBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const { libzcash::SaplingIncomingViewingKey ivk; - - // If we have a SaplingExtendedSpendingKey in the wallet, then we will - // also have the corresponding SaplingExtendedFullViewingKey. return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) && m_wallet->HaveSaplingFullViewingKey(ivk); } bool PaymentAddressBelongsToWallet::operator()(const libzcash::UnifiedAddress &uaddr) const { - // TODO - return false; + return m_wallet->FindUnifiedFullViewingKey(uaddr).has_value(); } // GetSourceForPaymentAddress -PaymentAddressSource GetSourceForPaymentAddress::operator()(const CKeyID &zaddr) const +PaymentAddressSource GetSourceForPaymentAddress::GetUnifiedSource(const libzcash::Receiver& receiver) const { - // TODO - return AddressNotFound; + auto hdChain = m_wallet->GetMnemonicHDChain(); + auto ufvkMeta = m_wallet->GetUFVKMetadataForReceiver(receiver); + if (ufvkMeta.has_value()) { + auto ufvkid = ufvkMeta.value().first; + // Look through the UFVKs that we have generated, and confirm that the + // seed fingerprint for the key we find for the ufvkid corresponds to + // the wallet's mnemonic seed. + for (const auto& [k, v] : m_wallet->mapUnifiedAccountKeys) { + if (v == ufvkid && hdChain.has_value() && k.first == hdChain.value().GetSeedFingerprint()) { + return PaymentAddressSource::MnemonicHDSeed; + } + } + return PaymentAddressSource::ImportedWatchOnly; + } else { + return PaymentAddressSource::AddressNotFound; + } } -PaymentAddressSource GetSourceForPaymentAddress::operator()(const CScriptID &zaddr) const + +PaymentAddressSource GetSourceForPaymentAddress::operator()(const CKeyID &addr) const { - // TODO - return AddressNotFound; + auto ufvkSource = this->GetUnifiedSource(addr); + if (ufvkSource == PaymentAddressSource::AddressNotFound) { + if (m_wallet->HaveKey(addr)) { + return PaymentAddressSource::Random; + } else { + if (m_wallet->HaveWatchOnly(GetScriptForDestination(addr))) { + return PaymentAddressSource::ImportedWatchOnly; + } + } + } + + return ufvkSource; +} +PaymentAddressSource GetSourceForPaymentAddress::operator()(const CScriptID &addr) const +{ + auto ufvkSource = this->GetUnifiedSource(addr); + if (ufvkSource == PaymentAddressSource::AddressNotFound) { + if (m_wallet->HaveCScript(addr)) { + return PaymentAddressSource::Imported; + } else if (m_wallet->HaveWatchOnly(GetScriptForDestination(addr))) { + return PaymentAddressSource::ImportedWatchOnly; + } + } + + return ufvkSource; } PaymentAddressSource GetSourceForPaymentAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) const { - return Random; + if (m_wallet->HaveSproutSpendingKey(zaddr)) { + return PaymentAddressSource::Random; + } else if (m_wallet->HaveSproutViewingKey(zaddr)) { + return PaymentAddressSource::ImportedWatchOnly; + } else { + return PaymentAddressSource::AddressNotFound; + } } PaymentAddressSource GetSourceForPaymentAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const { - libzcash::SaplingIncomingViewingKey ivk; + auto ufvkSource = this->GetUnifiedSource(zaddr); + if (ufvkSource == PaymentAddressSource::AddressNotFound) { + libzcash::SaplingIncomingViewingKey ivk; - // If we have a SaplingExtendedSpendingKey in the wallet, then we will - // also have the corresponding SaplingExtendedFullViewingKey. - if (m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk)) { - if (m_wallet->HaveSaplingFullViewingKey(ivk)) { - // If we have the HD keypath, it's related to the legacy seed - if (m_wallet->mapSaplingZKeyMetadata.count(ivk) > 0 && - m_wallet->mapSaplingZKeyMetadata[ivk].hdKeypath != "") { - return LegacyHDSeed; - } else if (m_wallet->HaveSaplingSpendingKeyForAddress(zaddr)) { - return Imported; + // If we have a SaplingExtendedSpendingKey in the wallet, then we will + // also have the corresponding SaplingExtendedFullViewingKey. + if (m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk)) { + if (m_wallet->HaveSaplingFullViewingKey(ivk)) { + // If we have the HD keypath, it's related to the legacy seed + if (m_wallet->mapSaplingZKeyMetadata.count(ivk) > 0 && + m_wallet->mapSaplingZKeyMetadata[ivk].hdKeypath != "") { + return PaymentAddressSource::LegacyHDSeed; + } else if (m_wallet->HaveSaplingSpendingKeyForAddress(zaddr)) { + return PaymentAddressSource::Imported; + } else { + return PaymentAddressSource::ImportedWatchOnly; + } } else { - return ImportedWatchOnly; + return PaymentAddressSource::ImportedWatchOnly; } - } else { - return ImportedWatchOnly; } - } else { - return AddressNotFound; } + + return ufvkSource; } PaymentAddressSource GetSourceForPaymentAddress::operator()(const libzcash::UnifiedAddress &uaddr) const { - // TODO - return AddressNotFound; + auto hdChain = m_wallet->GetMnemonicHDChain(); + auto ufvkid = m_wallet->FindUnifiedFullViewingKey(uaddr); + if (ufvkid.has_value()) { + // Look through the UFVKs that we have generated, and confirm that the + // seed fingerprint for the key we find for the ufvkid corresponds to + // the wallet's mnemonic seed. + for (const auto& [k, v] : m_wallet->mapUnifiedAccountKeys) { + if (v == ufvkid.value() && hdChain.has_value() && k.first == hdChain.value().GetSeedFingerprint()) { + return PaymentAddressSource::MnemonicHDSeed; + } + } + return PaymentAddressSource::ImportedWatchOnly; + } else { + return PaymentAddressSource::AddressNotFound; + } } // GetViewingKeyForPaymentAddress diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 855eefdbf..cd8c69040 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1799,7 +1799,7 @@ public: std::optional operator()(const libzcash::UnifiedAddress &uaddr) const; }; -enum PaymentAddressSource { +enum class PaymentAddressSource { Random, LegacyHDSeed, MnemonicHDSeed, @@ -1815,6 +1815,8 @@ private: public: GetSourceForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {} + PaymentAddressSource GetUnifiedSource(const libzcash::Receiver& receiver) const; + PaymentAddressSource operator()(const CKeyID &zaddr) const; PaymentAddressSource operator()(const CScriptID &zaddr) const; PaymentAddressSource operator()(const libzcash::SproutPaymentAddress &zaddr) const;