#ifndef ZC_ADDRESS_H_ #define ZC_ADDRESS_H_ #include "uint256.h" #include "zcash/address/sapling.hpp" #include "zcash/address/sprout.hpp" #include "zcash/address/zip32.h" #include namespace libzcash { // 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& vch) : uint160(vch) {} }; class P2SHAddress: public uint160 { public: P2SHAddress() {} explicit P2SHAddress(const std::vector& vch) : uint160(vch) {} }; /** Protocol addresses that can receive funds in a transaction. */ typedef std::variant RawAddress; class UnknownReceiver { public: uint32_t typecode; std::vector data; UnknownReceiver(uint32_t typecode, std::vector data) : 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 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 sortedReceivers; size_t cur; }; class UnifiedAddress { std::vector receivers; std::vector 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& 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; } }; /** Addresses that can appear in a string encoding. */ typedef std::variant< SproutPaymentAddress, SaplingPaymentAddress, UnifiedAddress> PaymentAddress; /** 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; class AddressInfoFromSpendingKey { public: std::pair operator()(const SproutSpendingKey&) const; std::pair operator()(const struct SaplingExtendedSpendingKey&) const; }; class AddressInfoFromViewingKey { public: std::pair operator()(const SproutViewingKey&) const; std::pair operator()(const struct SaplingExtendedFullViewingKey&) const; }; } /** * Gets the typecode for the given UA receiver. */ class TypecodeForReceiver { public: TypecodeForReceiver() {} 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; }; /** * Converts the given UA receiver to a protocol address, if it is a shielded receiver. */ class ReceiverToRawAddress { public: ReceiverToRawAddress() {} std::optional operator()(const libzcash::SaplingPaymentAddress &zaddr) const; std::optional operator()(const libzcash::P2SHAddress &p2sh) const; std::optional operator()(const libzcash::P2PKHAddress &p2pkh) const; std::optional operator()(const libzcash::UnknownReceiver &p2pkh) const; }; /** * Returns the protocol address that should be used in transaction outputs. */ class RecipientForPaymentAddress { public: RecipientForPaymentAddress() {} std::optional operator()(const libzcash::SproutPaymentAddress &zaddr) const; std::optional operator()(const libzcash::SaplingPaymentAddress &zaddr) const; std::optional operator()(const libzcash::UnifiedAddress &uaddr) const; }; /** * Returns all protocol addresses contained within the given payment address. */ class GetRawAddresses { public: GetRawAddresses() {} std::set operator()(const libzcash::SproutPaymentAddress &zaddr) const; std::set operator()(const libzcash::SaplingPaymentAddress &zaddr) const; std::set operator()(const libzcash::UnifiedAddress &uaddr) const; }; #endif // ZC_ADDRESS_H_