Add support for unified addresses to CWallet::ToZTXOSelector
This commit is contained in:
parent
f850e89449
commit
e419899a29
|
@ -61,7 +61,10 @@ AsyncRPCOperation_sendmany::AsyncRPCOperation_sendmany(
|
|||
|
||||
std::visit(match {
|
||||
[&](const AccountZTXOSelector& acct) {
|
||||
isfromtaddr_ = (acct.GetAccountId() == ZCASH_LEGACY_ACCOUNT);
|
||||
isfromtaddr_ =
|
||||
acct.GetReceiverTypes().empty() ||
|
||||
acct.GetReceiverTypes().count(ReceiverType::P2PKH) > 0 ||
|
||||
acct.GetReceiverTypes().count(ReceiverType::P2SH) > 0;
|
||||
},
|
||||
[&](const PaymentAddress& addr) {
|
||||
// We don't need to lock on the wallet as spending key related methods are thread-safe
|
||||
|
@ -252,6 +255,7 @@ uint256 AsyncRPCOperation_sendmany::main_impl() {
|
|||
// and send the extra to the recipient or the miner fee to avoid
|
||||
// creating dust change, rather than prohibit them from sending
|
||||
// entirely in this circumstance.
|
||||
// (Daira disagrees, as this could leak information to the recipient)
|
||||
throw JSONRPCError(
|
||||
RPC_WALLET_INSUFFICIENT_FUNDS,
|
||||
strprintf(
|
||||
|
|
|
@ -1359,9 +1359,13 @@ void CWallet::SyncMetaData(pair<typename TxSpendMap<T>::iterator, typename TxSpe
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Zcash transaction output selectors
|
||||
//
|
||||
|
||||
std::optional<ZTXOSelector> CWallet::ToZTXOSelector(const libzcash::PaymentAddress& addr, bool requireSpendingKey) const {
|
||||
auto self = this;
|
||||
std::optional<ZTXOSelector> result;
|
||||
std::optional<ZTXOSelector> result = std::nullopt;
|
||||
std::visit(match {
|
||||
[&](const CKeyID& addr) {
|
||||
if (!requireSpendingKey || self->HaveKey(addr)) {
|
||||
|
@ -1384,7 +1388,21 @@ std::optional<ZTXOSelector> CWallet::ToZTXOSelector(const libzcash::PaymentAddre
|
|||
}
|
||||
},
|
||||
[&](const libzcash::UnifiedAddress& ua) {
|
||||
// TODO: Find the unified account corresponding to this UA
|
||||
auto ufvkId = this->FindUnifiedFullViewingKey(ua);
|
||||
if (ufvkId.has_value()) {
|
||||
// TODO: at present, the `false` value for the `requireSpendingKey` argument
|
||||
// is not respected for unified addresses, because we have no notion of
|
||||
// an account for which we do not control the spending key. An alternate
|
||||
// approach would be to use the UFVK directly in the case that we cannot
|
||||
// determine a local account.
|
||||
auto addrMetaIt = mapUfvkAddressMetadata.find(ufvkId.value());
|
||||
if (addrMetaIt != mapUfvkAddressMetadata.end()) {
|
||||
auto accountId = addrMetaIt->second.GetAccountId();
|
||||
if (accountId.has_value()) {
|
||||
result = AccountZTXOSelector(accountId.value(), ua.GetKnownReceiverTypes());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}, addr);
|
||||
return result;
|
||||
|
@ -5700,8 +5718,31 @@ void CWallet::GetFilteredNotes(
|
|||
}
|
||||
}
|
||||
|
||||
std::optional<UFVKId> CWallet::FindUnifiedFullViewingKey(const libzcash::UnifiedAddress& addr) const {
|
||||
std::optional<libzcash::UFVKId> ufvkId;
|
||||
for (const auto& receiver : addr) {
|
||||
// skip unknown receivers
|
||||
if (libzcash::HasKnownReceiverType(receiver)) {
|
||||
auto ufvkPair = this->GetUFVKMetadataForReceiver(receiver);
|
||||
if (ufvkPair.has_value()) {
|
||||
if (ufvkId.has_value()) {
|
||||
// Check that all the receivers belong to the same ufvk; if not,
|
||||
// we cannot identify a unique UFVK for the address.
|
||||
if (ufvkPair.value().first != ufvkId.value()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
} else {
|
||||
ufvkId = ufvkPair.value().first;
|
||||
}
|
||||
} else {
|
||||
return std::nullopt;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ufvkId;
|
||||
}
|
||||
|
||||
std::optional<UnifiedAddress> CWallet::GetUnifiedForReceiver(const Receiver& receiver) {
|
||||
std::optional<UnifiedAddress> CWallet::GetUnifiedForReceiver(const Receiver& receiver) const {
|
||||
return std::visit(LookupUnifiedAddress(*this), receiver);
|
||||
}
|
||||
|
||||
|
|
|
@ -846,6 +846,10 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
std::optional<libzcash::AccountId> GetAccountId() const {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
bool SetAccountId(libzcash::AccountId accountIdIn) {
|
||||
if (accountId.has_value()) {
|
||||
return (accountIdIn == accountId.value());
|
||||
|
@ -1358,7 +1362,8 @@ public:
|
|||
bool LoadUnifiedAccountMetadata(const ZcashdUnifiedAccountMetadata &skmeta);
|
||||
bool LoadUnifiedAddressMetadata(const ZcashdUnifiedAddressMetadata &addrmeta);
|
||||
|
||||
std::optional<libzcash::UnifiedAddress> GetUnifiedForReceiver(const libzcash::Receiver& receiver);
|
||||
std::optional<libzcash::UFVKId> FindUnifiedFullViewingKey(const libzcash::UnifiedAddress& addr) const;
|
||||
std::optional<libzcash::UnifiedAddress> GetUnifiedForReceiver(const libzcash::Receiver& receiver) const;
|
||||
|
||||
/**
|
||||
* Increment the next transaction order id
|
||||
|
|
|
@ -73,6 +73,14 @@ std::optional<SaplingPaymentAddress> UnifiedAddress::GetSaplingReceiver() const
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
bool HasKnownReceiverType(const Receiver& receiver) {
|
||||
return std::visit(match {
|
||||
[](const SaplingPaymentAddress& addr) { return true; },
|
||||
[](const CScriptID& addr) { return true; },
|
||||
[](const CKeyID& addr) { return true; },
|
||||
[](const UnknownReceiver& addr) { return false; }
|
||||
}, receiver);
|
||||
}
|
||||
|
||||
std::pair<std::string, PaymentAddress> AddressInfoFromSpendingKey::operator()(const SproutSpendingKey &sk) const {
|
||||
return std::make_pair("sprout", sk.address());
|
||||
|
|
|
@ -56,6 +56,8 @@ typedef std::variant<
|
|||
CKeyID,
|
||||
UnknownReceiver> Receiver;
|
||||
|
||||
bool HasKnownReceiverType(const Receiver& receiver);
|
||||
|
||||
struct ReceiverIterator {
|
||||
using iterator_category = std::random_access_iterator_tag;
|
||||
using difference_type = std::ptrdiff_t;
|
||||
|
|
Loading…
Reference in New Issue