Add unified address support to GetSourceForPaymentAddress

This commit is contained in:
Kris Nuttycombe 2022-02-09 18:59:13 -07:00
parent d2e8b98364
commit f320a6cc24
3 changed files with 100 additions and 32 deletions

View File

@ -500,7 +500,7 @@ UniValue listaddresses(const UniValue& params, bool fHelp)
UniValue sapling_obj(UniValue::VOBJ); UniValue sapling_obj(UniValue::VOBJ);
if (source == LegacyHDSeed || source == MnemonicHDSeed) { if (source == PaymentAddressSource::LegacyHDSeed || source == PaymentAddressSource::MnemonicHDSeed) {
std::string hdKeyPath = pwalletMain->mapSaplingZKeyMetadata[ivk].hdKeypath; std::string hdKeyPath = pwalletMain->mapSaplingZKeyMetadata[ivk].hdKeypath;
if (hdKeyPath != "") { if (hdKeyPath != "") {
sapling_obj.pushKV("zip32KeyPath", hdKeyPath); sapling_obj.pushKV("zip32KeyPath", hdKeyPath);
@ -531,7 +531,7 @@ UniValue listaddresses(const UniValue& params, bool fHelp)
{ {
UniValue imported_sprout_addrs(UniValue::VARR); UniValue imported_sprout_addrs(UniValue::VARR);
for (const SproutPaymentAddress& addr : sproutAddresses) { for (const SproutPaymentAddress& addr : sproutAddresses) {
if (GetSourceForPaymentAddress(pwalletMain)(addr) == Imported) { if (GetSourceForPaymentAddress(pwalletMain)(addr) == PaymentAddressSource::Imported) {
imported_sprout_addrs.push_back(keyIO.EncodePaymentAddress(addr)); 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) { if (hasData) {
ret.push_back(entry); ret.push_back(entry);
@ -573,7 +573,7 @@ UniValue listaddresses(const UniValue& params, bool fHelp)
{ {
UniValue watchonly_sprout_addrs(UniValue::VARR); UniValue watchonly_sprout_addrs(UniValue::VARR);
for (const SproutPaymentAddress& addr : sproutAddresses) { for (const SproutPaymentAddress& addr : sproutAddresses) {
if (GetSourceForPaymentAddress(pwalletMain)(addr) == ImportedWatchOnly) { if (GetSourceForPaymentAddress(pwalletMain)(addr) == PaymentAddressSource::ImportedWatchOnly) {
watchonly_sprout_addrs.push_back(keyIO.EncodePaymentAddress(addr)); 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) { if (hasData) {
ret.push_back(entry); ret.push_back(entry);
@ -598,7 +598,7 @@ UniValue listaddresses(const UniValue& params, bool fHelp)
UniValue entry(UniValue::VOBJ); UniValue entry(UniValue::VOBJ);
entry.pushKV("source", "legacy_hdseed"); entry.pushKV("source", "legacy_hdseed");
bool hasData = add_sapling(saplingAddresses, LegacyHDSeed, entry); bool hasData = add_sapling(saplingAddresses, PaymentAddressSource::LegacyHDSeed, entry);
if (hasData) { if (hasData) {
ret.push_back(entry); ret.push_back(entry);

View File

@ -6146,48 +6146,114 @@ bool PaymentAddressBelongsToWallet::operator()(const libzcash::UnifiedAddress &u
// GetSourceForPaymentAddress // GetSourceForPaymentAddress
PaymentAddressSource GetSourceForPaymentAddress::operator()(const CKeyID &zaddr) const PaymentAddressSource GetSourceForPaymentAddress::GetUnifiedSource(const libzcash::Receiver& receiver) const
{ {
// TODO auto hdChain = m_wallet->GetMnemonicHDChain();
return AddressNotFound; assert(hdChain.has_value());
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 && 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 auto ufvkSource = this->GetUnifiedSource(addr);
return AddressNotFound; 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 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 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 // If we have a SaplingExtendedSpendingKey in the wallet, then we will
// also have the corresponding SaplingExtendedFullViewingKey. // also have the corresponding SaplingExtendedFullViewingKey.
if (m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk)) { if (m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk)) {
if (m_wallet->HaveSaplingFullViewingKey(ivk)) { if (m_wallet->HaveSaplingFullViewingKey(ivk)) {
// If we have the HD keypath, it's related to the legacy seed // If we have the HD keypath, it's related to the legacy seed
if (m_wallet->mapSaplingZKeyMetadata.count(ivk) > 0 && if (m_wallet->mapSaplingZKeyMetadata.count(ivk) > 0 &&
m_wallet->mapSaplingZKeyMetadata[ivk].hdKeypath != "") { m_wallet->mapSaplingZKeyMetadata[ivk].hdKeypath != "") {
return LegacyHDSeed; return PaymentAddressSource::LegacyHDSeed;
} else if (m_wallet->HaveSaplingSpendingKeyForAddress(zaddr)) { } else if (m_wallet->HaveSaplingSpendingKeyForAddress(zaddr)) {
return Imported; return PaymentAddressSource::Imported;
} else {
return PaymentAddressSource::ImportedWatchOnly;
}
} else { } else {
return ImportedWatchOnly; return PaymentAddressSource::ImportedWatchOnly;
} }
} else {
return ImportedWatchOnly;
} }
} else {
return AddressNotFound;
} }
return ufvkSource;
} }
PaymentAddressSource GetSourceForPaymentAddress::operator()(const libzcash::UnifiedAddress &uaddr) const PaymentAddressSource GetSourceForPaymentAddress::operator()(const libzcash::UnifiedAddress &uaddr) const
{ {
// TODO auto hdChain = m_wallet->GetMnemonicHDChain();
return AddressNotFound; assert(hdChain.has_value());
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() && k.first == hdChain.value().GetSeedFingerprint()) {
return PaymentAddressSource::MnemonicHDSeed;
}
}
return PaymentAddressSource::ImportedWatchOnly;
} else {
return PaymentAddressSource::AddressNotFound;
}
} }
// GetViewingKeyForPaymentAddress // GetViewingKeyForPaymentAddress

View File

@ -1781,7 +1781,7 @@ public:
std::optional<libzcash::ViewingKey> operator()(const libzcash::UnifiedAddress &uaddr) const; std::optional<libzcash::ViewingKey> operator()(const libzcash::UnifiedAddress &uaddr) const;
}; };
enum PaymentAddressSource { enum class PaymentAddressSource {
Random, Random,
LegacyHDSeed, LegacyHDSeed,
MnemonicHDSeed, MnemonicHDSeed,
@ -1797,6 +1797,8 @@ private:
public: public:
GetSourceForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {} GetSourceForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {}
PaymentAddressSource GetUnifiedSource(const libzcash::Receiver& receiver) const;
PaymentAddressSource operator()(const CKeyID &zaddr) const; PaymentAddressSource operator()(const CKeyID &zaddr) const;
PaymentAddressSource operator()(const CScriptID &zaddr) const; PaymentAddressSource operator()(const CScriptID &zaddr) const;
PaymentAddressSource operator()(const libzcash::SproutPaymentAddress &zaddr) const; PaymentAddressSource operator()(const libzcash::SproutPaymentAddress &zaddr) const;