diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d9f44fce5..439dd75b7 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -3136,7 +3136,7 @@ UniValue z_getaddressforaccount(const UniValue& params, bool fHelp) } if (receivers.empty()) { // Default is the best and second-best shielded pools, and the transparent pool. - receivers = {ReceiverType::P2PKH, ReceiverType::Sapling, ReceiverType::Orchard}; + receivers = CWallet::DefaultReceiverTypes(); } std::optional j = std::nullopt; diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index fe97e6035..44f3c241f 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -61,6 +61,10 @@ const char * DEFAULT_WALLET_DAT = "wallet.dat"; */ CFeeRate CWallet::minTxFee = CFeeRate(DEFAULT_TRANSACTION_MINFEE); +std::set CWallet::DefaultReceiverTypes() { + return {ReceiverType::P2PKH, ReceiverType::Sapling, ReceiverType::Orchard}; +} + /** @defgroup mapWallet * * @{ @@ -857,10 +861,12 @@ PaymentAddress CWallet::GetPaymentAddressForRecipient( const uint256& txid, const libzcash::RecipientAddress& recipient) const { + auto self = this; auto defaultAddress = [&]() -> PaymentAddress { + auto ufvk = self->GetUFVKForReceiver(RecipientAddressToReceiver(recipient)); return std::visit(match { [&](const CKeyID& addr) { - auto ua = pwalletMain->FindUnifiedAddressByReceiver(addr); + auto ua = self->FindUnifiedAddressByReceiver(addr); if (ua.has_value()) { return libzcash::PaymentAddress{ua.value()}; } else { @@ -868,7 +874,7 @@ PaymentAddress CWallet::GetPaymentAddressForRecipient( } }, [&](const CScriptID& addr) { - auto ua = pwalletMain->FindUnifiedAddressByReceiver(addr); + auto ua = self->FindUnifiedAddressByReceiver(addr); if (ua.has_value()) { return libzcash::PaymentAddress{ua.value()}; } else { @@ -876,20 +882,37 @@ PaymentAddress CWallet::GetPaymentAddressForRecipient( } }, [&](const SaplingPaymentAddress& addr) { - auto ua = pwalletMain->FindUnifiedAddressByReceiver(addr); + auto ua = self->FindUnifiedAddressByReceiver(addr); if (ua.has_value()) { return libzcash::PaymentAddress{ua.value()}; + } else if (ufvk.has_value() && ufvk->GetSaplingKey().has_value()) { + auto saplingKey = ufvk->GetSaplingKey().value(); + auto j = saplingKey.DecryptDiversifier(addr.d); + // std::get is safe here because we know we have a valid Sapling diversifier index + auto defaultUA = std::get>( + ufvk->Address(j, CWallet::DefaultReceiverTypes())); + return libzcash::PaymentAddress{defaultUA.first}; } else { return libzcash::PaymentAddress{addr}; } }, [&](const OrchardRawAddress& addr) { - auto ua = pwalletMain->FindUnifiedAddressByReceiver(addr); + auto ua = self->FindUnifiedAddressByReceiver(addr); if (ua.has_value()) { return libzcash::PaymentAddress{ua.value()}; - } else { - return libzcash::PaymentAddress{UnifiedAddress::ForSingleReceiver(addr)}; + } else if (ufvk.has_value() && ufvk->GetOrchardKey().has_value()) { + auto orchardKey = ufvk->GetOrchardKey().value(); + auto j = orchardKey.ToIncomingViewingKey().DecryptDiversifier(addr); + if (j.has_value()) { + auto genResult = ufvk->Address(j.value(), CWallet::DefaultReceiverTypes()); + auto defaultUA = std::get_if>(&genResult); + if (defaultUA != nullptr) { + return libzcash::PaymentAddress{defaultUA->first}; + } + } } + + return libzcash::PaymentAddress{UnifiedAddress::ForSingleReceiver(addr)}; } }, recipient); }; @@ -913,6 +936,7 @@ PaymentAddress CWallet::GetPaymentAddressForRecipient( bool CWallet::IsInternalRecipient(const libzcash::RecipientAddress& recipient) const { + auto self = this; return std::visit(match { [&](const CKeyID& addr) { // we never send transparent change when sending to or from a @@ -924,7 +948,7 @@ bool CWallet::IsInternalRecipient(const libzcash::RecipientAddress& recipient) c return false; }, [&](const SaplingPaymentAddress& addr) { - auto ufvk = pwalletMain->GetUFVKForReceiver(addr); + auto ufvk = self->GetUFVKForReceiver(addr); if (ufvk.has_value()) { auto changeAddr = ufvk->GetChangeAddress(SaplingChangeRequest()); if (changeAddr.has_value()) { @@ -934,7 +958,7 @@ bool CWallet::IsInternalRecipient(const libzcash::RecipientAddress& recipient) c return false; }, [&](const OrchardRawAddress& addr) { - auto ufvk = pwalletMain->GetUFVKForReceiver(addr); + auto ufvk = self->GetUFVKForReceiver(addr); if (ufvk.has_value()) { auto changeAddr = ufvk->GetChangeAddress(OrchardChangeRequest()); if (changeAddr.has_value()) { @@ -1583,7 +1607,7 @@ set CWallet::GetConflicts(const uint256& txid) const for (uint32_t i = 0; i < wtx.GetOrchardBundle().GetNumActions(); i++) { OrchardOutPoint op(wtx.GetHash(), i); - auto potential_spends = pwalletMain->orchardWallet.GetPotentialSpends(op); + auto potential_spends = orchardWallet.GetPotentialSpends(op); if (potential_spends.size() <= 1) { continue; // No conflict if zero or one spends @@ -3691,7 +3715,7 @@ bool CWallet::MnemonicVerified() { } HDSeed CWallet::GetHDSeedForRPC() const { - auto seed = pwalletMain->GetMnemonicSeed(); + auto seed = GetMnemonicSeed(); if (!seed.has_value()) { throw JSONRPCError(RPC_WALLET_ERROR, "HD seed not found"); } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index cefd742b7..709b892c8 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -1704,6 +1704,12 @@ public: */ static CAmount GetRequiredFee(unsigned int nTxBytes); + /** + * The current set of default receiver types used when the wallet generates + * unified addresses + */ + static std::set DefaultReceiverTypes(); + private: bool NewKeyPool(); public: