2017-11-23 11:20:20 -08:00
|
|
|
#ifndef ZC_ADDRESS_H_
|
|
|
|
#define ZC_ADDRESS_H_
|
2016-05-04 17:25:42 -07:00
|
|
|
|
2021-06-30 09:41:06 -07:00
|
|
|
#include "uint256.h"
|
2020-02-18 07:28:04 -08:00
|
|
|
#include "zcash/address/sapling.hpp"
|
|
|
|
#include "zcash/address/sprout.hpp"
|
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>
|
2018-04-25 18:51:17 -07:00
|
|
|
|
2016-05-04 17:25:42 -07:00
|
|
|
namespace libzcash {
|
2021-06-30 09:41:06 -07:00
|
|
|
// We use new classes here instead of CKeyID and CScriptID to prevent a cyclic dependency.
|
|
|
|
class P2PKHAddress: public uint160 {
|
|
|
|
public:
|
|
|
|
P2PKHAddress() {}
|
|
|
|
explicit P2PKHAddress(const std::vector<unsigned char>& vch) : uint160(vch) {}
|
|
|
|
};
|
|
|
|
class P2SHAddress: public uint160 {
|
|
|
|
public:
|
|
|
|
P2SHAddress() {}
|
|
|
|
explicit P2SHAddress(const std::vector<unsigned char>& vch) : uint160(vch) {}
|
|
|
|
};
|
|
|
|
|
2021-06-29 11:49:00 -07:00
|
|
|
/** Protocol addresses that can receive funds in a transaction. */
|
|
|
|
typedef std::variant<SproutPaymentAddress, SaplingPaymentAddress> RawAddress;
|
|
|
|
|
2021-06-30 09:41:06 -07:00
|
|
|
class UnknownReceiver {
|
|
|
|
public:
|
2021-09-16 15:58:18 -07:00
|
|
|
uint32_t typecode;
|
2021-06-30 09:41:06 -07:00
|
|
|
std::vector<uint8_t> data;
|
|
|
|
|
2021-09-16 15:58:18 -07:00
|
|
|
UnknownReceiver(uint32_t typecode, std::vector<uint8_t> data) :
|
2021-06-30 09:41:06 -07:00
|
|
|
typecode(typecode), data(data) {}
|
|
|
|
|
|
|
|
friend inline bool operator==(const UnknownReceiver& a, const UnknownReceiver& b) {
|
|
|
|
return a.typecode == b.typecode && a.data == b.data;
|
|
|
|
}
|
|
|
|
friend inline bool operator<(const UnknownReceiver& a, const UnknownReceiver& b) {
|
|
|
|
// We don't know for certain the preference order of unknown receivers, but it is
|
|
|
|
// _likely_ that the higher typecode has higher preference. The exact sort order
|
|
|
|
// doesn't really matter, as unknown receivers have lower preference than known
|
|
|
|
// receivers.
|
|
|
|
return (a.typecode > b.typecode ||
|
|
|
|
(a.typecode == b.typecode && a.data < b.data));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Receivers that can appear in a Unified Address.
|
|
|
|
*
|
|
|
|
* These types are given in order of preference (as defined in ZIP 316), so that sorting
|
|
|
|
* variants by `operator<` is equivalent to sorting by preference.
|
|
|
|
*/
|
|
|
|
typedef std::variant<
|
|
|
|
SaplingPaymentAddress,
|
|
|
|
P2SHAddress,
|
|
|
|
P2PKHAddress,
|
|
|
|
UnknownReceiver> Receiver;
|
|
|
|
|
|
|
|
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;
|
|
|
|
};
|
|
|
|
|
|
|
|
class UnifiedAddress {
|
|
|
|
std::vector<Receiver> receivers;
|
|
|
|
|
|
|
|
std::vector<const Receiver*> GetSorted() const;
|
|
|
|
|
|
|
|
public:
|
|
|
|
UnifiedAddress() {}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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);
|
|
|
|
|
|
|
|
const std::vector<Receiver>& GetReceiversAsParsed() const { return receivers; }
|
|
|
|
|
|
|
|
ReceiverIterator begin() const {
|
|
|
|
return ReceiverIterator(GetSorted(), 0);
|
|
|
|
}
|
|
|
|
ReceiverIterator end() const {
|
|
|
|
return ReceiverIterator(GetSorted(), receivers.size());
|
|
|
|
}
|
|
|
|
size_t size() const {
|
|
|
|
return receivers.size();
|
|
|
|
}
|
|
|
|
|
|
|
|
friend inline bool operator==(const UnifiedAddress& a, const UnifiedAddress& b) {
|
|
|
|
return a.receivers == b.receivers;
|
|
|
|
}
|
|
|
|
friend inline bool operator<(const UnifiedAddress& a, const UnifiedAddress& b) {
|
|
|
|
return a.receivers < b.receivers;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
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<
|
|
|
|
SproutPaymentAddress,
|
|
|
|
SaplingPaymentAddress,
|
|
|
|
UnifiedAddress> PaymentAddress;
|
2021-12-16 15:28:43 -08:00
|
|
|
/** Viewing keys that can have a string encoding. */
|
|
|
|
typedef std::variant<
|
|
|
|
SproutViewingKey,
|
|
|
|
SaplingExtendedFullViewingKey> ViewingKey;
|
|
|
|
/** Spending keys that can have a string encoding. */
|
|
|
|
typedef std::variant<
|
|
|
|
SproutSpendingKey,
|
|
|
|
SaplingExtendedSpendingKey> SpendingKey;
|
2018-06-06 21:40:59 -07: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 {
|
2020-04-06 13:11:50 -07:00
|
|
|
public:
|
|
|
|
std::pair<std::string, PaymentAddress> operator()(const SproutViewingKey&) const;
|
|
|
|
std::pair<std::string, PaymentAddress> operator()(const struct SaplingExtendedFullViewingKey&) const;
|
|
|
|
};
|
|
|
|
|
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() {}
|
|
|
|
|
2021-09-16 15:58:18 -07:00
|
|
|
uint32_t operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
|
|
|
|
uint32_t operator()(const libzcash::P2SHAddress &p2sh) const;
|
|
|
|
uint32_t operator()(const libzcash::P2PKHAddress &p2pkh) const;
|
|
|
|
uint32_t operator()(const libzcash::UnknownReceiver &p2pkh) const;
|
2021-06-30 09:41:06 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Converts the given UA receiver to a protocol address, if it is a shielded receiver.
|
|
|
|
*/
|
|
|
|
class ReceiverToRawAddress {
|
|
|
|
public:
|
|
|
|
ReceiverToRawAddress() {}
|
|
|
|
|
|
|
|
std::optional<libzcash::RawAddress> operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
|
|
|
|
std::optional<libzcash::RawAddress> operator()(const libzcash::P2SHAddress &p2sh) const;
|
|
|
|
std::optional<libzcash::RawAddress> operator()(const libzcash::P2PKHAddress &p2pkh) const;
|
|
|
|
std::optional<libzcash::RawAddress> operator()(const libzcash::UnknownReceiver &p2pkh) const;
|
|
|
|
};
|
|
|
|
|
2021-06-29 11:49:00 -07:00
|
|
|
/**
|
|
|
|
* Returns the protocol address that should be used in transaction outputs.
|
|
|
|
*/
|
|
|
|
class RecipientForPaymentAddress {
|
|
|
|
public:
|
|
|
|
RecipientForPaymentAddress() {}
|
|
|
|
|
|
|
|
std::optional<libzcash::RawAddress> operator()(const libzcash::SproutPaymentAddress &zaddr) const;
|
|
|
|
std::optional<libzcash::RawAddress> operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
|
2021-06-30 09:41:06 -07:00
|
|
|
std::optional<libzcash::RawAddress> operator()(const libzcash::UnifiedAddress &uaddr) const;
|
2021-06-29 11:49:00 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Returns all protocol addresses contained within the given payment address.
|
|
|
|
*/
|
|
|
|
class GetRawAddresses {
|
|
|
|
public:
|
|
|
|
GetRawAddresses() {}
|
|
|
|
|
|
|
|
std::set<libzcash::RawAddress> operator()(const libzcash::SproutPaymentAddress &zaddr) const;
|
|
|
|
std::set<libzcash::RawAddress> operator()(const libzcash::SaplingPaymentAddress &zaddr) const;
|
2021-06-30 09:41:06 -07:00
|
|
|
std::set<libzcash::RawAddress> operator()(const libzcash::UnifiedAddress &uaddr) const;
|
2021-06-29 11:49:00 -07:00
|
|
|
};
|
|
|
|
|
2017-11-23 11:20:20 -08:00
|
|
|
#endif // ZC_ADDRESS_H_
|