Add raw transparent address types to PaymentAddress

The addition of `UnifiedAddress` to the `PaymentAddress` type
introduced the need for methods that interact with payment addresses
to support transparent receivers as shielded ones, which is somewhat
inconsistent with previous uses of the `PaymentAddress` type.

This commit adds both `CKeyID` and `CScriptID` as new variants
of the `PaymentAddress` type. Following commits will shift encoding
and decoding to use the `PaymentAddress` type exclusively wherever
possible, rather than the current mix of `CDestination` and
`PaymentAddress` that complicates the wallet codebase.
This commit is contained in:
Kris Nuttycombe 2021-12-23 15:08:11 -07:00
parent c35e2b4438
commit 890e1d841d
11 changed files with 295 additions and 100 deletions

View File

@ -1678,18 +1678,12 @@ bool AppInit2(boost::thread_group& threadGroup, CScheduler& scheduler)
#ifdef ENABLE_WALLET #ifdef ENABLE_WALLET
bool minerAddressInLocalWallet = false; bool minerAddressInLocalWallet = false;
if (pwalletMain) { if (pwalletMain) {
CTxDestination addr = keyIO.DecodeDestination(mapArgs["-mineraddress"]); auto zaddr = keyIO.DecodePaymentAddress(mapArgs["-mineraddress"]);
if (IsValidDestination(addr)) { if (!zaddr.has_value()) {
CKeyID keyID = std::get<CKeyID>(addr); return InitError(_("-mineraddress is not a valid zcash address."));
minerAddressInLocalWallet = pwalletMain->HaveKey(keyID);
} else {
auto zaddr = keyIO.DecodePaymentAddress(mapArgs["-mineraddress"]);
if (!zaddr.has_value()) {
return InitError(_("-mineraddress is not a valid zcash address."));
}
minerAddressInLocalWallet = std::visit(
HaveSpendingKeyForPaymentAddress(pwalletMain), zaddr.value());
} }
minerAddressInLocalWallet = std::visit(
HaveSpendingKeyForPaymentAddress(pwalletMain), zaddr.value());
} }
if (GetBoolArg("-minetolocalwallet", true) && !minerAddressInLocalWallet) { if (GetBoolArg("-minetolocalwallet", true) && !minerAddressInLocalWallet) {
return InitError(_("-mineraddress is not in the local wallet. Either use a local address, or set -minetolocalwallet=0")); return InitError(_("-mineraddress is not in the local wallet. Either use a local address, or set -minetolocalwallet=0"));

View File

@ -16,6 +16,7 @@
#include <string.h> #include <string.h>
#include <algorithm> #include <algorithm>
#include <variant> #include <variant>
#include "util/match.h"
namespace namespace
{ {
@ -113,6 +114,18 @@ private:
public: public:
PaymentAddressEncoder(const KeyConstants& keyConstants) : keyConstants(keyConstants) {} PaymentAddressEncoder(const KeyConstants& keyConstants) : keyConstants(keyConstants) {}
std::string operator()(const CKeyID& id) const
{
std::vector<unsigned char> data = keyConstants.Base58Prefix(KeyConstants::PUBKEY_ADDRESS);
data.insert(data.end(), id.begin(), id.end());
return EncodeBase58Check(data);
}
std::string operator()(const CScriptID& id) const
{
std::vector<unsigned char> data = keyConstants.Base58Prefix(KeyConstants::SCRIPT_ADDRESS);
data.insert(data.end(), id.begin(), id.end());
return EncodeBase58Check(data);
}
std::string operator()(const libzcash::SproutPaymentAddress& zaddr) const std::string operator()(const libzcash::SproutPaymentAddress& zaddr) const
{ {
CDataStream ss(SER_NETWORK, PROTOCOL_VERSION); CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
@ -349,17 +362,16 @@ std::string KeyIO::EncodePaymentAddress(const libzcash::PaymentAddress& zaddr)
return std::visit(PaymentAddressEncoder(keyConstants), zaddr); return std::visit(PaymentAddressEncoder(keyConstants), zaddr);
} }
template<typename T1, typename T2, typename T3> template<typename T1, typename T2>
std::optional<T1> DecodeAny( std::optional<T1> DecodeSprout(
const KeyConstants& keyConstants, const KeyConstants& keyConstants,
const std::string& str, const std::string& str,
std::pair<KeyConstants::Base58Type, size_t> sprout, const std::pair<KeyConstants::Base58Type, size_t>& keyMeta)
std::pair<KeyConstants::Bech32Type, size_t> sapling)
{ {
std::vector<unsigned char> data; std::vector<unsigned char> data;
if (DecodeBase58Check(str, data)) { if (DecodeBase58Check(str, data)) {
const std::vector<unsigned char>& prefix = keyConstants.Base58Prefix(sprout.first); const std::vector<unsigned char>& prefix = keyConstants.Base58Prefix(keyMeta.first);
if ((data.size() == sprout.second + prefix.size()) && if ((data.size() == keyMeta.second + prefix.size()) &&
std::equal(prefix.begin(), prefix.end(), data.begin())) { std::equal(prefix.begin(), prefix.end(), data.begin())) {
CSerializeData serialized(data.begin() + prefix.size(), data.end()); CSerializeData serialized(data.begin() + prefix.size(), data.end());
CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION); CDataStream ss(serialized, SER_NETWORK, PROTOCOL_VERSION);
@ -371,15 +383,26 @@ std::optional<T1> DecodeAny(
} }
} }
data.clear(); memory_cleanse(data.data(), data.size());
return std::nullopt;
}
template<typename T1, typename T2>
std::optional<T1> DecodeSapling(
const KeyConstants& keyConstants,
const std::string& str,
const std::pair<KeyConstants::Bech32Type, size_t>& keyMeta)
{
std::vector<unsigned char> data;
auto bech = bech32::Decode(str); auto bech = bech32::Decode(str);
if (bech.first == keyConstants.Bech32HRP(sapling.first) && if (bech.first == keyConstants.Bech32HRP(keyMeta.first) &&
bech.second.size() == sapling.second) { bech.second.size() == keyMeta.second) {
// Bech32 decoding // Bech32 decoding
data.reserve((bech.second.size() * 5) / 8); data.reserve((bech.second.size() * 5) / 8);
if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) { if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) {
CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION); CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
T3 ret; T2 ret;
ss >> ret; ss >> ret;
memory_cleanse(data.data(), data.size()); memory_cleanse(data.data(), data.size());
return ret; return ret;
@ -390,6 +413,26 @@ std::optional<T1> DecodeAny(
return std::nullopt; return std::nullopt;
} }
template<typename T1, typename T2, typename T3>
std::optional<T1> DecodeAny(
const KeyConstants& keyConstants,
const std::string& str,
const std::pair<KeyConstants::Base58Type, size_t>& sproutKeyMeta,
const std::pair<KeyConstants::Bech32Type, size_t>& saplingKeyMeta)
{
auto sprout = DecodeSprout<T1, T2>(keyConstants, str, sproutKeyMeta);
if (sprout.has_value()) {
return sprout.value();
}
auto sapling = DecodeSapling<T1, T3>(keyConstants, str, saplingKeyMeta);
if (sapling.has_value()) {
return sapling.value();
}
return std::nullopt;
}
/** /**
* `raw` MUST be 43 bytes. * `raw` MUST be 43 bytes.
*/ */
@ -457,15 +500,39 @@ std::optional<libzcash::PaymentAddress> KeyIO::DecodePaymentAddress(const std::s
return ua; return ua;
} }
// Fall back on trying Sprout or Sapling. // Try parsing as a Sapling address
return DecodeAny<libzcash::PaymentAddress, auto sapling = DecodeSapling<libzcash::SaplingPaymentAddress, libzcash::SaplingPaymentAddress>(
libzcash::SproutPaymentAddress,
libzcash::SaplingPaymentAddress>(
keyConstants, keyConstants,
str, str,
std::make_pair(KeyConstants::ZCPAYMENT_ADDRESS, libzcash::SerializedSproutPaymentAddressSize), std::make_pair(KeyConstants::SAPLING_PAYMENT_ADDRESS, ConvertedSaplingPaymentAddressSize));
std::make_pair(KeyConstants::SAPLING_PAYMENT_ADDRESS, ConvertedSaplingPaymentAddressSize) if (sapling.has_value()) {
); return sapling.value();
}
// Try parsing as a Sprout address
auto sprout = DecodeSprout<libzcash::SproutPaymentAddress, libzcash::SproutPaymentAddress>(
keyConstants,
str,
std::make_pair(KeyConstants::ZCPAYMENT_ADDRESS, libzcash::SerializedSproutPaymentAddressSize));
if (sprout.has_value()) {
return sprout.value();
}
// Finally, try parsing as transparent
return std::visit(match {
[](const CKeyID& keyIdIn) {
std::optional<libzcash::PaymentAddress> keyId = keyIdIn;
return keyId;
},
[](const CScriptID& scriptIdIn) {
std::optional<libzcash::PaymentAddress> scriptId = scriptIdIn;
return scriptId;
},
[](const CNoDestination& d) {
std::optional<libzcash::PaymentAddress> result = std::nullopt;
return result;
}
}, DecodeDestination(str));
} }
bool KeyIO::IsValidPaymentAddressString(const std::string& str) { bool KeyIO::IsValidPaymentAddressString(const std::string& str) {

View File

@ -32,6 +32,12 @@ class ExtractMinerAddress
public: public:
ExtractMinerAddress() {} ExtractMinerAddress() {}
std::optional<MinerAddress> operator()(const CKeyID &addr) const {
return std::nullopt;
}
std::optional<MinerAddress> operator()(const CScriptID &addr) const {
return std::nullopt;
}
std::optional<MinerAddress> operator()(const libzcash::SproutPaymentAddress &addr) const { std::optional<MinerAddress> operator()(const libzcash::SproutPaymentAddress &addr) const {
return std::nullopt; return std::nullopt;
} }
@ -40,7 +46,7 @@ public:
} }
std::optional<MinerAddress> operator()(const libzcash::UnifiedAddress &addr) const { std::optional<MinerAddress> operator()(const libzcash::UnifiedAddress &addr) const {
auto recipient = RecipientForPaymentAddress()(addr); auto recipient = RecipientForPaymentAddress()(addr);
if (recipient) { if (recipient.has_value()) {
// This looks like a recursive call, but we are actually calling // This looks like a recursive call, but we are actually calling
// ExtractMinerAddress with a different type: // ExtractMinerAddress with a different type:
// - libzcash::PaymentAddress has a libzcash::UnifiedAddress // - libzcash::PaymentAddress has a libzcash::UnifiedAddress
@ -51,7 +57,7 @@ public:
// This works because std::visit does not require the visitor to // This works because std::visit does not require the visitor to
// solely match the std::variant, only that it can handle all of // solely match the std::variant, only that it can handle all of
// the variant's alternatives. // the variant's alternatives.
return std::visit(ExtractMinerAddress(), *recipient); return std::visit(ExtractMinerAddress(), recipient.value());
} else { } else {
// Either the UA only contains unknown shielded receivers (unlikely that we // Either the UA only contains unknown shielded receivers (unlikely that we
// wouldn't know about them), or it only contains transparent receivers // wouldn't know about them), or it only contains transparent receivers

View File

@ -217,6 +217,28 @@ UniValue validateaddress(const UniValue& params, bool fHelp)
class DescribePaymentAddressVisitor class DescribePaymentAddressVisitor
{ {
public: public:
UniValue operator()(const CKeyID &addr) const {
UniValue obj(UniValue::VOBJ);
obj.pushKV("type", "p2pkh");
#ifdef ENABLE_WALLET
if (pwalletMain) {
obj.pushKV("ismine", pwalletMain->HaveKey(addr));
}
#endif
return obj;
}
UniValue operator()(const CScriptID &addr) const {
UniValue obj(UniValue::VOBJ);
obj.pushKV("type", "p2sh");
#ifdef ENABLE_WALLET
if (pwalletMain) {
obj.pushKV("ismine", pwalletMain->HaveCScript(addr));
}
#endif
return obj;
}
UniValue operator()(const libzcash::SproutPaymentAddress &zaddr) const { UniValue operator()(const libzcash::SproutPaymentAddress &zaddr) const {
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.pushKV("type", "sprout"); obj.pushKV("type", "sprout");

View File

@ -202,6 +202,14 @@ bool AsyncRPCOperation_shieldcoinbase::main_impl() {
return std::visit(ShieldToAddress(this, sendAmount), tozaddr_); return std::visit(ShieldToAddress(this, sendAmount), tozaddr_);
} }
bool ShieldToAddress::operator()(const CKeyID &addr) const {
return false;
}
bool ShieldToAddress::operator()(const CScriptID &addr) const {
return false;
}
bool ShieldToAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) const { bool ShieldToAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) const {
// update the transaction with these inputs // update the transaction with these inputs
CMutableTransaction rawTx(m_op->tx_); CMutableTransaction rawTx(m_op->tx_);

View File

@ -103,6 +103,8 @@ public:
ShieldToAddress(AsyncRPCOperation_shieldcoinbase *op, CAmount sendAmount) : ShieldToAddress(AsyncRPCOperation_shieldcoinbase *op, CAmount sendAmount) :
m_op(op), sendAmount(sendAmount) {} m_op(op), sendAmount(sendAmount) {}
bool operator()(const CKeyID &zaddr) const;
bool operator()(const CScriptID &zaddr) const;
bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SproutPaymentAddress &zaddr) const;
bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
bool operator()(const libzcash::UnifiedAddress &uaddr) const; bool operator()(const libzcash::UnifiedAddress &uaddr) const;

View File

@ -2273,7 +2273,7 @@ UniValue z_listunspent(const UniValue& params, bool fHelp)
// We want to return unspent notes corresponding to any receiver within a // We want to return unspent notes corresponding to any receiver within a
// Unified Address. // Unified Address.
for (const auto ra : std::visit(GetRawAddresses(), zaddr.value())) { for (const auto ra : std::visit(GetRawShieldedAddresses(), zaddr.value())) {
bool hasSpendingKey = std::visit(match { bool hasSpendingKey = std::visit(match {
[&](const SaplingPaymentAddress& addr) { [&](const SaplingPaymentAddress& addr) {
return pwalletMain->HaveSaplingSpendingKeyForAddress(addr); return pwalletMain->HaveSaplingSpendingKeyForAddress(addr);
@ -3154,10 +3154,16 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, decoded, nMinDepth, false, false); pwalletMain->GetFilteredNotes(sproutEntries, saplingEntries, decoded, nMinDepth, false, false);
std::visit(match { std::visit(match {
[&](const CKeyID& addr) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transparent addresses are not supported by this endpoint.");
},
[&](const CScriptID& addr) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transparent addresses are not supported by this endpoint.");
},
[&](const libzcash::SproutPaymentAddress& addr) { [&](const libzcash::SproutPaymentAddress& addr) {
bool hasSpendingKey = pwalletMain->HaveSproutSpendingKey(addr); bool hasSpendingKey = pwalletMain->HaveSproutSpendingKey(addr);
auto nullifierSet = pwalletMain->GetNullifiersForAddresses({addr}); auto nullifierSet = pwalletMain->GetNullifiersForAddresses({addr});
for (SproutNoteEntry & entry : sproutEntries) { for (const SproutNoteEntry& entry : sproutEntries) {
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.pushKV("txid", entry.jsop.hash.ToString()); obj.pushKV("txid", entry.jsop.hash.ToString());
obj.pushKV("amount", ValueFromAmount(CAmount(entry.note.value()))); obj.pushKV("amount", ValueFromAmount(CAmount(entry.note.value())));
@ -3182,7 +3188,7 @@ UniValue z_listreceivedbyaddress(const UniValue& params, bool fHelp)
[&](const libzcash::SaplingPaymentAddress& addr) { [&](const libzcash::SaplingPaymentAddress& addr) {
bool hasSpendingKey = pwalletMain->HaveSaplingSpendingKeyForAddress(addr); bool hasSpendingKey = pwalletMain->HaveSaplingSpendingKeyForAddress(addr);
auto nullifierSet = pwalletMain->GetNullifiersForAddresses({addr}); auto nullifierSet = pwalletMain->GetNullifiersForAddresses({addr});
for (SaplingNoteEntry & entry : saplingEntries) { for (const SaplingNoteEntry& entry : saplingEntries) {
UniValue obj(UniValue::VOBJ); UniValue obj(UniValue::VOBJ);
obj.pushKV("txid", entry.op.hash.ToString()); obj.pushKV("txid", entry.op.hash.ToString());
obj.pushKV("amount", ValueFromAmount(CAmount(entry.note.value()))); obj.pushKV("amount", ValueFromAmount(CAmount(entry.note.value())));
@ -3895,6 +3901,12 @@ UniValue z_sendmany(const UniValue& params, bool fHelp)
if (decoded.has_value()) { if (decoded.has_value()) {
std::visit(match { std::visit(match {
[&](const CKeyID&) {
// Handled elsewhere
},
[&](const CScriptID&) {
// Handled elsewhere
},
[&](const libzcash::SaplingPaymentAddress& addr) { [&](const libzcash::SaplingPaymentAddress& addr) {
mtx.vShieldedOutput.push_back(OutputDescription()); mtx.vShieldedOutput.push_back(OutputDescription());
}, },
@ -4458,7 +4470,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
if (zaddr.has_value()) { if (zaddr.has_value()) {
// We want to merge notes corresponding to any receiver within a // We want to merge notes corresponding to any receiver within a
// Unified Address. // Unified Address.
for (const libzcash::RawAddress& ra : std::visit(GetRawAddresses(), zaddr.value())) { for (const libzcash::RawAddress& ra : std::visit(GetRawShieldedAddresses(), zaddr.value())) {
zaddrs.insert(ra); zaddrs.insert(ra);
if (std::holds_alternative<libzcash::SaplingPaymentAddress>(ra)) { if (std::holds_alternative<libzcash::SaplingPaymentAddress>(ra)) {
isFromNonSprout = true; isFromNonSprout = true;
@ -4489,30 +4501,34 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
// Validate the destination address // Validate the destination address
auto destaddress = params[1].get_str(); auto destaddress = params[1].get_str();
bool isToTaddr = false;
bool isToSproutZaddr = false; bool isToSproutZaddr = false;
bool isToSaplingZaddr = false; bool isToSaplingZaddr = false;
CTxDestination taddr = keyIO.DecodeDestination(destaddress); auto paymentAddress = keyIO.DecodePaymentAddress(destaddress);
if (!IsValidDestination(taddr)) { if (paymentAddress.has_value()) {
auto zaddr = keyIO.DecodePaymentAddress(destaddress); std::visit(match {
if (zaddr.has_value()) { [&](CKeyID addr) {
std::visit(match { isToTaddr = true;
[&](libzcash::SaplingPaymentAddress addr) { },
isToSaplingZaddr = true; [&](CScriptID addr) {
// If Sapling is not active, do not allow sending to a sapling addresses. isToTaddr = true;
if (!saplingActive) { },
throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated"); [&](libzcash::SaplingPaymentAddress addr) {
} isToSaplingZaddr = true;
}, // If Sapling is not active, do not allow sending to a sapling addresses.
[&](libzcash::SproutPaymentAddress addr) { if (!saplingActive) {
isToSproutZaddr = true; throw JSONRPCError(RPC_INVALID_PARAMETER, "Invalid parameter, Sapling has not activated");
},
[&](libzcash::UnifiedAddress) {
// TODO UNIFIED
} }
}, zaddr.value()); },
} else { [&](libzcash::SproutPaymentAddress addr) {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress ); isToSproutZaddr = true;
} },
[&](libzcash::UnifiedAddress) {
// TODO UNIFIED
}
}, paymentAddress.value());
} else {
throw JSONRPCError(RPC_INVALID_PARAMETER, string("Invalid parameter, unknown address format: ") + destaddress );
} }
if (canopyActive && isFromNonSprout && isToSproutZaddr) { if (canopyActive && isFromNonSprout && isToSproutZaddr) {
@ -4750,7 +4766,7 @@ UniValue z_mergetoaddress(const UniValue& params, bool fHelp)
contextInfo.pushKV("toaddress", params[1]); contextInfo.pushKV("toaddress", params[1]);
contextInfo.pushKV("fee", ValueFromAmount(nFee)); contextInfo.pushKV("fee", ValueFromAmount(nFee));
if (!sproutNoteInputs.empty() || !saplingNoteInputs.empty() || !IsValidDestination(taddr)) { if (!sproutNoteInputs.empty() || !saplingNoteInputs.empty() || !isToTaddr) {
// We have shielded inputs or the recipient is a shielded address, and // We have shielded inputs or the recipient is a shielded address, and
// therefore we cannot create transactions before Sapling activates. // therefore we cannot create transactions before Sapling activates.
if (!saplingActive) { if (!saplingActive) {

View File

@ -5041,7 +5041,7 @@ void CWallet::GetFilteredNotes(
std::set<libzcash::RawAddress> filterAddresses; std::set<libzcash::RawAddress> filterAddresses;
if (address.has_value()) { if (address.has_value()) {
for (const auto ra : std::visit(GetRawAddresses(), address.value())) { for (const auto ra : std::visit(GetRawShieldedAddresses(), address.value())) {
filterAddresses.insert(ra); filterAddresses.insert(ra);
} }
} }
@ -5185,37 +5185,57 @@ void CWallet::GetFilteredNotes(
// //
// Shielded key and address generalizations // Payment address operations
// //
// PaymentAddressBelongsToWallet
bool PaymentAddressBelongsToWallet::operator()(const CKeyID &addr) const
{
CScript script = GetScriptForDestination(addr);
return m_wallet->HaveKey(addr) || m_wallet->HaveWatchOnly(script);
}
bool PaymentAddressBelongsToWallet::operator()(const CScriptID &addr) const
{
CScript script = GetScriptForDestination(addr);
return m_wallet->HaveCScript(addr) || m_wallet->HaveWatchOnly(script);
}
bool PaymentAddressBelongsToWallet::operator()(const libzcash::SproutPaymentAddress &zaddr) const bool PaymentAddressBelongsToWallet::operator()(const libzcash::SproutPaymentAddress &zaddr) const
{ {
return m_wallet->HaveSproutSpendingKey(zaddr) || m_wallet->HaveSproutViewingKey(zaddr); return m_wallet->HaveSproutSpendingKey(zaddr) || m_wallet->HaveSproutViewingKey(zaddr);
} }
bool PaymentAddressBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const bool PaymentAddressBelongsToWallet::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
{ {
libzcash::SaplingIncomingViewingKey ivk; 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.
return m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) && return
m_wallet->GetSaplingIncomingViewingKey(zaddr, ivk) &&
m_wallet->HaveSaplingFullViewingKey(ivk); m_wallet->HaveSaplingFullViewingKey(ivk);
} }
bool PaymentAddressBelongsToWallet::operator()(const libzcash::UnifiedAddress &uaddr) const bool PaymentAddressBelongsToWallet::operator()(const libzcash::UnifiedAddress &uaddr) const
{ {
// TODO // TODO
return false; return false;
} }
/// // GetSourceForPaymentAddress
PaymentAddressSource GetSourceForPaymentAddress::operator()(const CKeyID &zaddr) const
{
// TODO
return AddressNotFound;
}
PaymentAddressSource GetSourceForPaymentAddress::operator()(const CScriptID &zaddr) const
{
// TODO
return AddressNotFound;
}
PaymentAddressSource GetSourceForPaymentAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) const PaymentAddressSource GetSourceForPaymentAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) const
{ {
return Random; return Random;
} }
PaymentAddressSource GetSourceForPaymentAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const PaymentAddressSource GetSourceForPaymentAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
{ {
libzcash::SaplingIncomingViewingKey ivk; libzcash::SaplingIncomingViewingKey ivk;
@ -5240,15 +5260,24 @@ PaymentAddressSource GetSourceForPaymentAddress::operator()(const libzcash::Sapl
return AddressNotFound; return AddressNotFound;
} }
} }
PaymentAddressSource GetSourceForPaymentAddress::operator()(const libzcash::UnifiedAddress &uaddr) const PaymentAddressSource GetSourceForPaymentAddress::operator()(const libzcash::UnifiedAddress &uaddr) const
{ {
// TODO // TODO
return AddressNotFound; return AddressNotFound;
} }
/// // GetViewingKeyForPaymentAddress
std::optional<libzcash::ViewingKey> GetViewingKeyForPaymentAddress::operator()(
const CKeyID &zaddr) const
{
return std::nullopt;
}
std::optional<libzcash::ViewingKey> GetViewingKeyForPaymentAddress::operator()(
const CScriptID &zaddr) const
{
return std::nullopt;
}
std::optional<libzcash::ViewingKey> GetViewingKeyForPaymentAddress::operator()( std::optional<libzcash::ViewingKey> GetViewingKeyForPaymentAddress::operator()(
const libzcash::SproutPaymentAddress &zaddr) const const libzcash::SproutPaymentAddress &zaddr) const
{ {
@ -5262,7 +5291,6 @@ std::optional<libzcash::ViewingKey> GetViewingKeyForPaymentAddress::operator()(
} }
return libzcash::ViewingKey(vk); return libzcash::ViewingKey(vk);
} }
std::optional<libzcash::ViewingKey> GetViewingKeyForPaymentAddress::operator()( std::optional<libzcash::ViewingKey> GetViewingKeyForPaymentAddress::operator()(
const libzcash::SaplingPaymentAddress &zaddr) const const libzcash::SaplingPaymentAddress &zaddr) const
{ {
@ -5277,19 +5305,27 @@ std::optional<libzcash::ViewingKey> GetViewingKeyForPaymentAddress::operator()(
return std::nullopt; return std::nullopt;
} }
} }
std::optional<libzcash::ViewingKey> GetViewingKeyForPaymentAddress::operator()( std::optional<libzcash::ViewingKey> GetViewingKeyForPaymentAddress::operator()(
const libzcash::UnifiedAddress &uaddr) const const libzcash::UnifiedAddress &uaddr) const
{ {
// TODO // TODO
return libzcash::ViewingKey(); return std::nullopt;
} }
// HaveSpendingKeyForPaymentAddress
bool HaveSpendingKeyForPaymentAddress::operator()(const CKeyID &addr) const
{
return m_wallet->HaveKey(addr);
}
bool HaveSpendingKeyForPaymentAddress::operator()(const CScriptID &addr) const
{
return m_wallet->HaveCScript(addr);
}
bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) const bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SproutPaymentAddress &zaddr) const
{ {
return m_wallet->HaveSproutSpendingKey(zaddr); return m_wallet->HaveSproutSpendingKey(zaddr);
} }
bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SaplingPaymentAddress &zaddr) const
{ {
libzcash::SaplingIncomingViewingKey ivk; libzcash::SaplingIncomingViewingKey ivk;
@ -5299,13 +5335,24 @@ bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::SaplingPayment
m_wallet->GetSaplingFullViewingKey(ivk, extfvk) && m_wallet->GetSaplingFullViewingKey(ivk, extfvk) &&
m_wallet->HaveSaplingSpendingKey(extfvk); m_wallet->HaveSaplingSpendingKey(extfvk);
} }
bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::UnifiedAddress &uaddr) const bool HaveSpendingKeyForPaymentAddress::operator()(const libzcash::UnifiedAddress &uaddr) const
{ {
// TODO // TODO
return false; return false;
} }
// GetSpendingKeyForPaymentAddress
std::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
const CKeyID &zaddr) const
{
return std::nullopt;
}
std::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
const CScriptID &zaddr) const
{
return std::nullopt;
}
std::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()( std::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
const libzcash::SproutPaymentAddress &zaddr) const const libzcash::SproutPaymentAddress &zaddr) const
{ {
@ -5316,7 +5363,6 @@ std::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()
return std::nullopt; return std::nullopt;
} }
} }
std::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()( std::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
const libzcash::SaplingPaymentAddress &zaddr) const const libzcash::SaplingPaymentAddress &zaddr) const
{ {
@ -5327,7 +5373,6 @@ std::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()
return std::nullopt; return std::nullopt;
} }
} }
std::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()( std::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()(
const libzcash::UnifiedAddress &uaddr) const const libzcash::UnifiedAddress &uaddr) const
{ {
@ -5335,6 +5380,8 @@ std::optional<libzcash::SpendingKey> GetSpendingKeyForPaymentAddress::operator()
return libzcash::SpendingKey(); return libzcash::SpendingKey();
} }
// AddViewingKeyToWallet
KeyAddResult AddViewingKeyToWallet::operator()(const libzcash::SproutViewingKey &vkey) const { KeyAddResult AddViewingKeyToWallet::operator()(const libzcash::SproutViewingKey &vkey) const {
auto addr = vkey.address(); auto addr = vkey.address();
@ -5348,7 +5395,6 @@ KeyAddResult AddViewingKeyToWallet::operator()(const libzcash::SproutViewingKey
return KeyNotAdded; return KeyNotAdded;
} }
} }
KeyAddResult AddViewingKeyToWallet::operator()(const libzcash::SaplingExtendedFullViewingKey &extfvk) const { KeyAddResult AddViewingKeyToWallet::operator()(const libzcash::SaplingExtendedFullViewingKey &extfvk) const {
if (m_wallet->HaveSaplingSpendingKey(extfvk)) { if (m_wallet->HaveSaplingSpendingKey(extfvk)) {
return SpendingKeyExists; return SpendingKeyExists;
@ -5361,6 +5407,8 @@ KeyAddResult AddViewingKeyToWallet::operator()(const libzcash::SaplingExtendedFu
} }
} }
// AddSpendingKeyToWallet
KeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SproutSpendingKey &sk) const { KeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SproutSpendingKey &sk) const {
auto addr = sk.address(); auto addr = sk.address();
KeyIO keyIO(Params()); KeyIO keyIO(Params());
@ -5376,7 +5424,6 @@ KeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SproutSpendingKe
return KeyNotAdded; return KeyNotAdded;
} }
} }
KeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingExtendedSpendingKey &sk) const { KeyAddResult AddSpendingKeyToWallet::operator()(const libzcash::SaplingExtendedSpendingKey &sk) const {
auto extfvk = sk.ToXFVK(); auto extfvk = sk.ToXFVK();
auto ivk = extfvk.fvk.in_viewing_key(); auto ivk = extfvk.fvk.in_viewing_key();

View File

@ -1369,6 +1369,8 @@ private:
public: public:
PaymentAddressBelongsToWallet(CWallet *wallet) : m_wallet(wallet) {} PaymentAddressBelongsToWallet(CWallet *wallet) : m_wallet(wallet) {}
bool operator()(const CKeyID &zaddr) const;
bool operator()(const CScriptID &zaddr) const;
bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SproutPaymentAddress &zaddr) const;
bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
bool operator()(const libzcash::UnifiedAddress &uaddr) const; bool operator()(const libzcash::UnifiedAddress &uaddr) const;
@ -1381,6 +1383,8 @@ private:
public: public:
GetViewingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {} GetViewingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {}
std::optional<libzcash::ViewingKey> operator()(const CKeyID &zaddr) const;
std::optional<libzcash::ViewingKey> operator()(const CScriptID &zaddr) const;
std::optional<libzcash::ViewingKey> operator()(const libzcash::SproutPaymentAddress &zaddr) const; std::optional<libzcash::ViewingKey> operator()(const libzcash::SproutPaymentAddress &zaddr) const;
std::optional<libzcash::ViewingKey> operator()(const libzcash::SaplingPaymentAddress &zaddr) const; std::optional<libzcash::ViewingKey> operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
std::optional<libzcash::ViewingKey> operator()(const libzcash::UnifiedAddress &uaddr) const; std::optional<libzcash::ViewingKey> operator()(const libzcash::UnifiedAddress &uaddr) const;
@ -1393,6 +1397,8 @@ private:
public: public:
HaveSpendingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {} HaveSpendingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {}
bool operator()(const CKeyID &addr) const;
bool operator()(const CScriptID &addr) const;
bool operator()(const libzcash::SproutPaymentAddress &zaddr) const; bool operator()(const libzcash::SproutPaymentAddress &zaddr) const;
bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const; bool operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
bool operator()(const libzcash::UnifiedAddress &uaddr) const; bool operator()(const libzcash::UnifiedAddress &uaddr) const;
@ -1405,8 +1411,11 @@ private:
public: public:
GetSpendingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {} GetSpendingKeyForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {}
std::optional<libzcash::SpendingKey> operator()(const CKeyID &zaddr) const;
std::optional<libzcash::SpendingKey> operator()(const CScriptID &zaddr) const;
std::optional<libzcash::SpendingKey> operator()(const libzcash::SproutPaymentAddress &zaddr) const; std::optional<libzcash::SpendingKey> operator()(const libzcash::SproutPaymentAddress &zaddr) const;
std::optional<libzcash::SpendingKey> operator()(const libzcash::SaplingPaymentAddress &zaddr) const; std::optional<libzcash::SpendingKey> operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
// FIXME: this doesn't make sense
std::optional<libzcash::SpendingKey> operator()(const libzcash::UnifiedAddress &uaddr) const; std::optional<libzcash::SpendingKey> operator()(const libzcash::UnifiedAddress &uaddr) const;
}; };
@ -1426,6 +1435,8 @@ private:
public: public:
GetSourceForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {} GetSourceForPaymentAddress(CWallet *wallet) : m_wallet(wallet) {}
PaymentAddressSource operator()(const CKeyID &zaddr) const;
PaymentAddressSource operator()(const CScriptID &zaddr) const;
PaymentAddressSource operator()(const libzcash::SproutPaymentAddress &zaddr) const; PaymentAddressSource operator()(const libzcash::SproutPaymentAddress &zaddr) const;
PaymentAddressSource operator()(const libzcash::SaplingPaymentAddress &zaddr) const; PaymentAddressSource operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
PaymentAddressSource operator()(const libzcash::UnifiedAddress &uaddr) const; PaymentAddressSource operator()(const libzcash::UnifiedAddress &uaddr) const;

View File

@ -56,61 +56,67 @@ uint32_t TypecodeForReceiver::operator()(
{ {
return ZCASH_UA_TYPECODE_SAPLING; return ZCASH_UA_TYPECODE_SAPLING;
} }
uint32_t TypecodeForReceiver::operator()( uint32_t TypecodeForReceiver::operator()(
const CScriptID &p2sh) const const CScriptID &p2sh) const
{ {
return ZCASH_UA_TYPECODE_P2SH; return ZCASH_UA_TYPECODE_P2SH;
} }
uint32_t TypecodeForReceiver::operator()( uint32_t TypecodeForReceiver::operator()(
const CKeyID &p2sh) const const CKeyID &p2sh) const
{ {
return ZCASH_UA_TYPECODE_P2PKH; return ZCASH_UA_TYPECODE_P2PKH;
} }
uint32_t TypecodeForReceiver::operator()( uint32_t TypecodeForReceiver::operator()(
const libzcash::UnknownReceiver &unknown) const const libzcash::UnknownReceiver &unknown) const
{ {
return unknown.typecode; return unknown.typecode;
} }
std::optional<libzcash::RawAddress> ReceiverToRawAddress::operator()( // ReceiverToRawAddress
const libzcash::SaplingPaymentAddress &zaddr) const
{
return zaddr;
}
std::optional<libzcash::RawAddress> ReceiverToRawAddress::operator()(
const CScriptID &p2sh) const
{
return std::nullopt;
}
std::optional<libzcash::RawAddress> ReceiverToRawAddress::operator()( std::optional<libzcash::RawAddress> ReceiverToRawAddress::operator()(
const CKeyID &p2sh) const const CKeyID &p2sh) const
{ {
return std::nullopt; return std::nullopt;
} }
std::optional<libzcash::RawAddress> ReceiverToRawAddress::operator()(
const CScriptID &p2sh) const
{
return std::nullopt;
}
std::optional<libzcash::RawAddress> ReceiverToRawAddress::operator()(
const libzcash::SaplingPaymentAddress &zaddr) const
{
return zaddr;
}
std::optional<libzcash::RawAddress> ReceiverToRawAddress::operator()( std::optional<libzcash::RawAddress> ReceiverToRawAddress::operator()(
const libzcash::UnknownReceiver &p2sh) const const libzcash::UnknownReceiver &p2sh) const
{ {
return std::nullopt; return std::nullopt;
} }
// RecipientForPaymentAddress
std::optional<libzcash::RawAddress> RecipientForPaymentAddress::operator()(
const CKeyID &p2sh) const
{
return std::nullopt;
}
std::optional<libzcash::RawAddress> RecipientForPaymentAddress::operator()(
const CScriptID &p2sh) const
{
return std::nullopt;
}
std::optional<libzcash::RawAddress> RecipientForPaymentAddress::operator()( std::optional<libzcash::RawAddress> RecipientForPaymentAddress::operator()(
const libzcash::SproutPaymentAddress &zaddr) const const libzcash::SproutPaymentAddress &zaddr) const
{ {
return zaddr; return zaddr;
} }
std::optional<libzcash::RawAddress> RecipientForPaymentAddress::operator()( std::optional<libzcash::RawAddress> RecipientForPaymentAddress::operator()(
const libzcash::SaplingPaymentAddress &zaddr) const const libzcash::SaplingPaymentAddress &zaddr) const
{ {
return zaddr; return zaddr;
} }
std::optional<libzcash::RawAddress> RecipientForPaymentAddress::operator()( std::optional<libzcash::RawAddress> RecipientForPaymentAddress::operator()(
const libzcash::UnifiedAddress &uaddr) const const libzcash::UnifiedAddress &uaddr) const
{ {
@ -122,19 +128,29 @@ std::optional<libzcash::RawAddress> RecipientForPaymentAddress::operator()(
return std::nullopt; return std::nullopt;
} }
std::set<libzcash::RawAddress> GetRawAddresses::operator()( // GetRawShieldedAddresses
std::set<libzcash::RawAddress> GetRawShieldedAddresses::operator()(
const CKeyID &addr) const
{
return {};
}
std::set<libzcash::RawAddress> GetRawShieldedAddresses::operator()(
const CScriptID &addr) const
{
return {};
}
std::set<libzcash::RawAddress> GetRawShieldedAddresses::operator()(
const libzcash::SproutPaymentAddress &zaddr) const const libzcash::SproutPaymentAddress &zaddr) const
{ {
return {zaddr}; return {zaddr};
} }
std::set<libzcash::RawAddress> GetRawShieldedAddresses::operator()(
std::set<libzcash::RawAddress> GetRawAddresses::operator()(
const libzcash::SaplingPaymentAddress &zaddr) const const libzcash::SaplingPaymentAddress &zaddr) const
{ {
return {zaddr}; return {zaddr};
} }
std::set<libzcash::RawAddress> GetRawShieldedAddresses::operator()(
std::set<libzcash::RawAddress> GetRawAddresses::operator()(
const libzcash::UnifiedAddress &uaddr) const const libzcash::UnifiedAddress &uaddr) const
{ {
std::set<libzcash::RawAddress> ret; std::set<libzcash::RawAddress> ret;

View File

@ -122,6 +122,8 @@ public:
/** Addresses that can appear in a string encoding. */ /** Addresses that can appear in a string encoding. */
typedef std::variant< typedef std::variant<
CKeyID,
CScriptID,
SproutPaymentAddress, SproutPaymentAddress,
SaplingPaymentAddress, SaplingPaymentAddress,
UnifiedAddress> PaymentAddress; UnifiedAddress> PaymentAddress;
@ -181,6 +183,8 @@ class RecipientForPaymentAddress {
public: public:
RecipientForPaymentAddress() {} RecipientForPaymentAddress() {}
std::optional<libzcash::RawAddress> operator()(const CKeyID &addr) const;
std::optional<libzcash::RawAddress> operator()(const CScriptID &addr) const;
std::optional<libzcash::RawAddress> operator()(const libzcash::SproutPaymentAddress &zaddr) const; std::optional<libzcash::RawAddress> operator()(const libzcash::SproutPaymentAddress &zaddr) const;
std::optional<libzcash::RawAddress> operator()(const libzcash::SaplingPaymentAddress &zaddr) const; std::optional<libzcash::RawAddress> operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
std::optional<libzcash::RawAddress> operator()(const libzcash::UnifiedAddress &uaddr) const; std::optional<libzcash::RawAddress> operator()(const libzcash::UnifiedAddress &uaddr) const;
@ -189,10 +193,12 @@ public:
/** /**
* Returns all protocol addresses contained within the given payment address. * Returns all protocol addresses contained within the given payment address.
*/ */
class GetRawAddresses { class GetRawShieldedAddresses {
public: public:
GetRawAddresses() {} GetRawShieldedAddresses() {}
std::set<libzcash::RawAddress> operator()(const CKeyID &addr) const;
std::set<libzcash::RawAddress> operator()(const CScriptID &addr) const;
std::set<libzcash::RawAddress> operator()(const libzcash::SproutPaymentAddress &zaddr) const; std::set<libzcash::RawAddress> operator()(const libzcash::SproutPaymentAddress &zaddr) const;
std::set<libzcash::RawAddress> operator()(const libzcash::SaplingPaymentAddress &zaddr) const; std::set<libzcash::RawAddress> operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
std::set<libzcash::RawAddress> operator()(const libzcash::UnifiedAddress &uaddr) const; std::set<libzcash::RawAddress> operator()(const libzcash::UnifiedAddress &uaddr) const;