2017-11-23 11:20:20 -08:00
|
|
|
#ifndef ZC_ADDRESS_H_
|
|
|
|
#define ZC_ADDRESS_H_
|
2016-05-04 17:25:42 -07:00
|
|
|
|
2022-02-23 09:20:11 -08:00
|
|
|
#include "consensus/params.h"
|
2021-11-29 15:40:29 -08:00
|
|
|
#include "key_constants.h"
|
2021-11-19 15:21:36 -08:00
|
|
|
#include "pubkey.h"
|
2021-11-29 19:04:37 -08:00
|
|
|
#include "key_constants.h"
|
2021-11-19 15:21:36 -08:00
|
|
|
#include "script/script.h"
|
2021-11-29 15:40:29 -08:00
|
|
|
#include "uint256.h"
|
2021-11-19 15:21:36 -08:00
|
|
|
#include "pubkey.h"
|
|
|
|
#include "script/script.h"
|
2021-12-22 17:20:53 -08:00
|
|
|
#include "util/match.h"
|
2021-07-19 15:06:52 -07:00
|
|
|
#include "zcash/address/orchard.hpp"
|
2020-02-18 07:28:04 -08:00
|
|
|
#include "zcash/address/sapling.hpp"
|
|
|
|
#include "zcash/address/sprout.hpp"
|
2021-11-29 15:40:29 -08:00
|
|
|
#include "zcash/address/unified.h"
|
2020-02-18 07:48:13 -08:00
|
|
|
#include "zcash/address/zip32.h"
|
2016-05-04 17:25:42 -07:00
|
|
|
|
2020-10-20 17:05:00 -07:00
|
|
|
#include <variant>
|
2022-05-26 09:09:30 -07:00
|
|
|
#include <rust/constants.h>
|
2021-11-29 15:40:29 -08:00
|
|
|
#include <rust/unified_keys.h>
|
2018-04-25 18:51:17 -07:00
|
|
|
|
2022-05-26 09:09:30 -07:00
|
|
|
const unsigned char ZCASH_UFVK_ID_PERSONAL[blake2b::PERSONALBYTES] =
|
2021-12-09 13:20:51 -08:00
|
|
|
{'Z', 'c', 'a', 's', 'h', '_', 'U', 'F', 'V', 'K', '_', 'I', 'd', '_', 'F', 'P'};
|
|
|
|
|
2016-05-04 17:25:42 -07:00
|
|
|
namespace libzcash {
|
2021-06-30 09:41:06 -07:00
|
|
|
|
2022-01-12 16:26:38 -08:00
|
|
|
bool HasKnownReceiverType(const Receiver& receiver);
|
|
|
|
|
2021-06-30 09:41:06 -07:00
|
|
|
struct ReceiverIterator {
|
|
|
|
using iterator_category = std::random_access_iterator_tag;
|
|
|
|
using difference_type = std::ptrdiff_t;
|
|
|
|
using value_type = const Receiver;
|
|
|
|
using pointer = const Receiver*;
|
|
|
|
using reference = const Receiver&;
|
|
|
|
|
|
|
|
ReceiverIterator(std::vector<const Receiver*> sorted, size_t cur) :
|
|
|
|
sortedReceivers(sorted), cur(cur) {}
|
|
|
|
|
|
|
|
reference operator*() const { return *sortedReceivers[cur]; }
|
|
|
|
pointer operator->() { return sortedReceivers[cur]; }
|
|
|
|
|
|
|
|
ReceiverIterator& operator++() { cur++; return *this; }
|
|
|
|
ReceiverIterator operator++(int) {
|
|
|
|
ReceiverIterator tmp = *this;
|
|
|
|
++(*this);
|
|
|
|
return tmp;
|
|
|
|
}
|
|
|
|
|
|
|
|
friend bool operator==(const ReceiverIterator& a, const ReceiverIterator& b) {
|
|
|
|
return a.sortedReceivers == b.sortedReceivers && a.cur == b.cur;
|
|
|
|
}
|
|
|
|
friend bool operator!=(const ReceiverIterator& a, const ReceiverIterator& b) {
|
|
|
|
return !(a == b);
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::vector<const Receiver*> sortedReceivers;
|
|
|
|
size_t cur;
|
|
|
|
};
|
|
|
|
|
2022-01-13 13:55:54 -08:00
|
|
|
|
2021-06-30 09:41:06 -07:00
|
|
|
class UnifiedAddress {
|
|
|
|
std::vector<Receiver> receivers;
|
|
|
|
|
|
|
|
std::vector<const Receiver*> GetSorted() const;
|
|
|
|
|
|
|
|
public:
|
|
|
|
UnifiedAddress() {}
|
|
|
|
|
2022-03-16 23:53:46 -07:00
|
|
|
static UnifiedAddress ForSingleReceiver(Receiver receiver) {
|
|
|
|
UnifiedAddress ua;
|
|
|
|
ua.AddReceiver(receiver);
|
|
|
|
return ua;
|
|
|
|
}
|
|
|
|
|
2022-02-17 17:27:15 -08:00
|
|
|
static std::optional<UnifiedAddress> Parse(const KeyConstants& keyConstants, const std::string& str);
|
|
|
|
|
2022-02-14 17:48:39 -08:00
|
|
|
ADD_SERIALIZE_METHODS;
|
|
|
|
|
|
|
|
template <typename Stream, typename Operation>
|
|
|
|
inline void SerializationOp(Stream& s, Operation ser_action) {
|
|
|
|
READWRITE(receivers);
|
|
|
|
}
|
|
|
|
|
2021-06-30 09:41:06 -07:00
|
|
|
/**
|
|
|
|
* Adds the given receiver to this unified address.
|
|
|
|
*
|
|
|
|
* Receivers are stored in the unified address (and its encoding) in the order they
|
|
|
|
* are added. When generating a new UA, call this method in preference order.
|
|
|
|
*
|
|
|
|
* Returns false if adding this receiver would result in an invalid unified address:
|
|
|
|
* - The UA already contains this receiver type.
|
|
|
|
* - The UA would contain both P2PKH and P2SH receivers.
|
|
|
|
*/
|
|
|
|
bool AddReceiver(Receiver receiver);
|
|
|
|
|
2022-02-21 19:35:46 -08:00
|
|
|
bool ContainsReceiver(const Receiver& receiver) const;
|
|
|
|
|
2021-06-30 09:41:06 -07:00
|
|
|
const std::vector<Receiver>& GetReceiversAsParsed() const { return receivers; }
|
|
|
|
|
2021-12-22 17:20:53 -08:00
|
|
|
std::set<ReceiverType> GetKnownReceiverTypes() const {
|
|
|
|
std::set<ReceiverType> result;
|
|
|
|
for (const auto& receiver : receivers) {
|
2023-04-04 13:26:39 -07:00
|
|
|
examine(receiver, match {
|
2022-02-18 15:18:40 -08:00
|
|
|
[&](const libzcash::OrchardRawAddress &zaddr) {
|
|
|
|
result.insert(ReceiverType::Orchard);
|
|
|
|
},
|
2021-12-22 17:20:53 -08:00
|
|
|
[&](const libzcash::SaplingPaymentAddress &zaddr) {
|
|
|
|
result.insert(ReceiverType::Sapling);
|
|
|
|
},
|
|
|
|
[&](const CScriptID &zaddr) {
|
|
|
|
result.insert(ReceiverType::P2SH);
|
|
|
|
},
|
|
|
|
[&](const CKeyID &zaddr) {
|
|
|
|
result.insert(ReceiverType::P2PKH);
|
|
|
|
},
|
|
|
|
[&](const libzcash::UnknownReceiver &uaddr) {
|
|
|
|
}
|
2023-04-04 13:26:39 -07:00
|
|
|
});
|
2021-12-22 17:20:53 -08:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-06-30 09:41:06 -07:00
|
|
|
ReceiverIterator begin() const {
|
|
|
|
return ReceiverIterator(GetSorted(), 0);
|
|
|
|
}
|
|
|
|
ReceiverIterator end() const {
|
|
|
|
return ReceiverIterator(GetSorted(), receivers.size());
|
|
|
|
}
|
|
|
|
size_t size() const {
|
|
|
|
return receivers.size();
|
|
|
|
}
|
|
|
|
|
2021-12-08 17:13:28 -08:00
|
|
|
std::optional<CKeyID> GetP2PKHReceiver() const;
|
|
|
|
|
|
|
|
std::optional<CScriptID> GetP2SHReceiver() const;
|
|
|
|
|
|
|
|
std::optional<SaplingPaymentAddress> GetSaplingReceiver() const;
|
|
|
|
|
2022-02-18 15:18:40 -08:00
|
|
|
std::optional<OrchardRawAddress> GetOrchardReceiver() const;
|
|
|
|
|
2022-01-25 08:15:51 -08:00
|
|
|
/**
|
|
|
|
* Return the most-preferred receiver from among the receiver types
|
2022-02-23 09:20:11 -08:00
|
|
|
* that we recognize and can use at the given block height.
|
2022-01-25 08:15:51 -08:00
|
|
|
*/
|
2022-02-23 09:20:11 -08:00
|
|
|
std::optional<RecipientAddress> GetPreferredRecipientAddress(
|
|
|
|
const Consensus::Params& consensus, int height) const;
|
2022-01-13 13:55:54 -08:00
|
|
|
|
2021-06-30 09:41:06 -07:00
|
|
|
friend inline bool operator==(const UnifiedAddress& a, const UnifiedAddress& b) {
|
|
|
|
return a.receivers == b.receivers;
|
|
|
|
}
|
2021-12-14 15:46:36 -08:00
|
|
|
friend inline bool operator!=(const UnifiedAddress& a, const UnifiedAddress& b) {
|
|
|
|
return a.receivers != b.receivers;
|
|
|
|
}
|
2021-06-30 09:41:06 -07:00
|
|
|
friend inline bool operator<(const UnifiedAddress& a, const UnifiedAddress& b) {
|
|
|
|
return a.receivers < b.receivers;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2021-11-29 15:40:29 -08:00
|
|
|
class UnifiedFullViewingKeyBuilder;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Wrapper for a zcash_address::unified::Ufvk.
|
|
|
|
*/
|
|
|
|
class UnifiedFullViewingKey {
|
|
|
|
private:
|
|
|
|
std::unique_ptr<UnifiedFullViewingKeyPtr, decltype(&unified_full_viewing_key_free)> inner;
|
|
|
|
|
|
|
|
UnifiedFullViewingKey() :
|
|
|
|
inner(nullptr, unified_full_viewing_key_free) {}
|
|
|
|
|
|
|
|
UnifiedFullViewingKey(UnifiedFullViewingKeyPtr* ptr) :
|
|
|
|
inner(ptr, unified_full_viewing_key_free) {}
|
|
|
|
|
|
|
|
friend class UnifiedFullViewingKeyBuilder;
|
|
|
|
public:
|
2021-11-29 19:04:37 -08:00
|
|
|
UnifiedFullViewingKey(UnifiedFullViewingKey&& key) : inner(std::move(key.inner)) {}
|
|
|
|
|
|
|
|
UnifiedFullViewingKey(const UnifiedFullViewingKey& key) :
|
|
|
|
inner(unified_full_viewing_key_clone(key.inner.get()), unified_full_viewing_key_free) {}
|
2021-11-29 15:40:29 -08:00
|
|
|
|
2021-12-13 20:00:05 -08:00
|
|
|
/**
|
|
|
|
* This method should only be used for serialization of unified full
|
|
|
|
* viewing keys that have been generated internally from unified spending
|
|
|
|
* keys by Zcashd. It is not suitable for use in any case where the
|
|
|
|
* ZcashdUnifiedFullViewingKey value may have been produced by a
|
|
|
|
* potentially-lossy conversion from a UnifiedFullViewingKey value that
|
|
|
|
* originated outside of zcashd.
|
|
|
|
*/
|
2021-11-29 15:40:29 -08:00
|
|
|
static UnifiedFullViewingKey FromZcashdUFVK(const ZcashdUnifiedFullViewingKey&);
|
|
|
|
|
2021-11-29 19:04:37 -08:00
|
|
|
static std::optional<UnifiedFullViewingKey> Decode(
|
|
|
|
const std::string& str,
|
|
|
|
const KeyConstants& keyConstants);
|
|
|
|
|
2021-11-29 15:40:29 -08:00
|
|
|
std::string Encode(const KeyConstants& keyConstants) const;
|
|
|
|
|
2022-02-18 16:41:38 -08:00
|
|
|
std::optional<OrchardFullViewingKey> GetOrchardKey() const;
|
|
|
|
|
2021-11-29 15:40:29 -08:00
|
|
|
std::optional<SaplingDiversifiableFullViewingKey> GetSaplingKey() const;
|
|
|
|
|
2022-02-11 15:25:04 -08:00
|
|
|
std::optional<transparent::AccountPubKey> GetTransparentKey() const;
|
2021-11-29 15:40:29 -08:00
|
|
|
|
2021-11-29 19:04:37 -08:00
|
|
|
UFVKId GetKeyID(const KeyConstants& keyConstants) const;
|
2021-11-29 15:40:29 -08:00
|
|
|
|
2022-02-09 12:49:36 -08:00
|
|
|
std::set<ReceiverType> GetKnownReceiverTypes() const {
|
|
|
|
std::set<ReceiverType> result;
|
|
|
|
if (GetTransparentKey().has_value()) {
|
|
|
|
result.insert(ReceiverType::P2PKH);
|
|
|
|
}
|
|
|
|
if (GetSaplingKey().has_value()) {
|
|
|
|
result.insert(ReceiverType::Sapling);
|
|
|
|
}
|
2022-02-18 16:41:38 -08:00
|
|
|
if (GetOrchardKey().has_value()) {
|
|
|
|
result.insert(ReceiverType::Orchard);
|
|
|
|
}
|
2022-02-09 12:49:36 -08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2021-11-29 15:40:29 -08:00
|
|
|
UnifiedFullViewingKey& operator=(UnifiedFullViewingKey&& key)
|
|
|
|
{
|
|
|
|
if (this != &key) {
|
|
|
|
inner = std::move(key.inner);
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
UnifiedFullViewingKey& operator=(const UnifiedFullViewingKey& key)
|
|
|
|
{
|
|
|
|
if (this != &key) {
|
|
|
|
inner.reset(unified_full_viewing_key_clone(key.inner.get()));
|
|
|
|
}
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
class UnifiedFullViewingKeyBuilder {
|
|
|
|
private:
|
|
|
|
std::optional<std::vector<uint8_t>> t_bytes;
|
|
|
|
std::optional<std::vector<uint8_t>> sapling_bytes;
|
2022-02-18 16:41:38 -08:00
|
|
|
std::optional<std::vector<uint8_t>> orchard_bytes;
|
2021-11-29 15:40:29 -08:00
|
|
|
public:
|
2022-02-18 16:41:38 -08:00
|
|
|
UnifiedFullViewingKeyBuilder():
|
|
|
|
t_bytes(std::nullopt),
|
|
|
|
sapling_bytes(std::nullopt),
|
|
|
|
orchard_bytes(std::nullopt) {}
|
2021-11-29 15:40:29 -08:00
|
|
|
|
2022-01-26 18:32:43 -08:00
|
|
|
bool AddTransparentKey(const transparent::AccountPubKey&);
|
2021-11-29 15:40:29 -08:00
|
|
|
bool AddSaplingKey(const SaplingDiversifiableFullViewingKey&);
|
2022-02-18 16:41:38 -08:00
|
|
|
bool AddOrchardKey(const OrchardFullViewingKey&);
|
2021-11-29 15:40:29 -08:00
|
|
|
|
|
|
|
std::optional<UnifiedFullViewingKey> build() const;
|
|
|
|
};
|
|
|
|
|
2021-06-29 11:49:00 -07:00
|
|
|
/** Addresses that can appear in a string encoding. */
|
2021-06-30 09:41:06 -07:00
|
|
|
typedef std::variant<
|
2021-12-23 14:08:11 -08:00
|
|
|
CKeyID,
|
|
|
|
CScriptID,
|
2021-06-30 09:41:06 -07:00
|
|
|
SproutPaymentAddress,
|
|
|
|
SaplingPaymentAddress,
|
|
|
|
UnifiedAddress> PaymentAddress;
|
2021-11-29 15:40:29 -08:00
|
|
|
/** Viewing keys that can have a string encoding. */
|
|
|
|
typedef std::variant<
|
|
|
|
SproutViewingKey,
|
|
|
|
SaplingExtendedFullViewingKey,
|
|
|
|
UnifiedFullViewingKey> ViewingKey;
|
|
|
|
/** Spending keys that can have a string encoding. */
|
|
|
|
typedef std::variant<
|
|
|
|
SproutSpendingKey,
|
|
|
|
SaplingExtendedSpendingKey> SpendingKey;
|
2018-06-06 21:40:59 -07:00
|
|
|
|
2022-05-26 15:28:35 -07:00
|
|
|
class HasShieldedRecipient {
|
2021-12-28 08:30:02 -08:00
|
|
|
public:
|
|
|
|
bool operator()(const CKeyID& p2pkh) { return false; }
|
|
|
|
bool operator()(const CScriptID& p2sh) { return false; }
|
|
|
|
bool operator()(const SproutPaymentAddress& addr) { return true; }
|
|
|
|
bool operator()(const SaplingPaymentAddress& addr) { return true; }
|
2022-05-26 15:28:35 -07:00
|
|
|
bool operator()(const UnifiedAddress& addr) { return true; }
|
2021-12-28 08:30:02 -08:00
|
|
|
};
|
|
|
|
|
2022-01-13 14:12:02 -08:00
|
|
|
class SelectRecipientAddress {
|
2022-02-23 09:20:11 -08:00
|
|
|
const Consensus::Params& consensus;
|
|
|
|
int height;
|
|
|
|
|
2022-01-13 14:12:02 -08:00
|
|
|
public:
|
2022-02-23 09:20:11 -08:00
|
|
|
SelectRecipientAddress(const Consensus::Params& consensus, int height) :
|
|
|
|
consensus(consensus), height(height) {}
|
|
|
|
|
2022-01-13 14:12:02 -08:00
|
|
|
std::optional<RecipientAddress> operator()(const CKeyID& p2pkh) { return p2pkh; }
|
|
|
|
std::optional<RecipientAddress> operator()(const CScriptID& p2sh) { return p2sh; }
|
|
|
|
std::optional<RecipientAddress> operator()(const SproutPaymentAddress& addr) { return std::nullopt; }
|
|
|
|
std::optional<RecipientAddress> operator()(const SaplingPaymentAddress& addr) { return addr; }
|
|
|
|
std::optional<RecipientAddress> operator()(const UnifiedAddress& addr) {
|
2022-02-23 09:20:11 -08:00
|
|
|
return addr.GetPreferredRecipientAddress(consensus, height);
|
2022-01-13 14:12:02 -08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-10-20 17:07:14 -07:00
|
|
|
class AddressInfoFromSpendingKey {
|
2019-11-11 15:49:11 -08:00
|
|
|
public:
|
|
|
|
std::pair<std::string, PaymentAddress> operator()(const SproutSpendingKey&) const;
|
|
|
|
std::pair<std::string, PaymentAddress> operator()(const struct SaplingExtendedSpendingKey&) const;
|
|
|
|
};
|
|
|
|
|
2020-10-20 17:07:14 -07:00
|
|
|
class AddressInfoFromViewingKey {
|
2021-12-22 12:26:32 -08:00
|
|
|
private:
|
|
|
|
const KeyConstants& keyConstants;
|
|
|
|
|
2020-04-06 13:11:50 -07:00
|
|
|
public:
|
2021-12-22 12:26:32 -08:00
|
|
|
AddressInfoFromViewingKey(const KeyConstants& keyConstants): keyConstants(keyConstants) {}
|
2020-04-06 13:11:50 -07:00
|
|
|
std::pair<std::string, PaymentAddress> operator()(const SproutViewingKey&) const;
|
|
|
|
std::pair<std::string, PaymentAddress> operator()(const struct SaplingExtendedFullViewingKey&) const;
|
2021-11-29 15:40:29 -08:00
|
|
|
std::pair<std::string, PaymentAddress> operator()(const UnifiedFullViewingKey&) const;
|
2020-04-06 13:11:50 -07:00
|
|
|
};
|
|
|
|
|
2021-11-29 15:40:29 -08:00
|
|
|
} //namespace libzcash
|
2016-05-04 17:25:42 -07:00
|
|
|
|
2021-06-30 09:41:06 -07:00
|
|
|
/**
|
|
|
|
* Gets the typecode for the given UA receiver.
|
|
|
|
*/
|
|
|
|
class TypecodeForReceiver {
|
|
|
|
public:
|
|
|
|
TypecodeForReceiver() {}
|
|
|
|
|
2022-02-18 15:18:40 -08:00
|
|
|
uint32_t operator()(const libzcash::OrchardRawAddress &zaddr) const;
|
2021-09-16 15:58:18 -07:00
|
|
|
uint32_t operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
|
2021-11-19 15:21:36 -08:00
|
|
|
uint32_t operator()(const CScriptID &p2sh) const;
|
|
|
|
uint32_t operator()(const CKeyID &p2pkh) const;
|
2021-09-16 15:58:18 -07:00
|
|
|
uint32_t operator()(const libzcash::UnknownReceiver &p2pkh) const;
|
2021-06-30 09:41:06 -07:00
|
|
|
};
|
|
|
|
|
2017-11-23 11:20:20 -08:00
|
|
|
#endif // ZC_ADDRESS_H_
|