PIVX Core  5.6.99
P2P Digital Currency
key_io_sapling.cpp
Go to the documentation of this file.
1 // Copyright (c) 2016-2018 The Zcash developers
2 // Copyright (c) 2020 The PIVX Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
5 
7 
8 #include "utilstrencodings.h"
9 #include "bech32.h"
10 #include "script/script.h"
11 #include "streams.h"
12 
13 #include <boost/variant/apply_visitor.hpp>
14 #include <boost/variant/static_visitor.hpp>
15 
16 #include <assert.h>
17 #include <string.h>
18 #include <algorithm>
19 
20 class PaymentAddressEncoder : public boost::static_visitor<std::string>
21 {
22 private:
24 
25 public:
26  explicit PaymentAddressEncoder(const CChainParams& params) : m_params(params) {}
27 
28  std::string operator()(const libzcash::SaplingPaymentAddress& zaddr) const
29  {
30  CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
31  ss << zaddr;
32  // ConvertBits requires unsigned char, but CDataStream uses char
33  std::vector<unsigned char> seraddr(ss.begin(), ss.end());
34  std::vector<unsigned char> data;
35  // See calculation comment below
36  data.reserve((seraddr.size() * 8 + 4) / 5);
37  ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, seraddr.begin(), seraddr.end());
39  }
40 
41  std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
42 };
43 
44 class ViewingKeyEncoder : public boost::static_visitor<std::string>
45 {
46 private:
48 
49 public:
50  explicit ViewingKeyEncoder(const CChainParams& params) : m_params(params) {}
51 
52  std::string operator()(const libzcash::SaplingExtendedFullViewingKey& extfvk) const
53  {
54  CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
55  ss << extfvk;
56  // ConvertBits requires unsigned char, but CDataStream uses char
57  std::vector<unsigned char> serkey(ss.begin(), ss.end());
58  std::vector<unsigned char> data;
59  // See calculation comment below
60  data.reserve((serkey.size() * 8 + 4) / 5);
61  ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, serkey.begin(), serkey.end());
63  memory_cleanse(serkey.data(), serkey.size());
64  memory_cleanse(data.data(), data.size());
65  return ret;
66  }
67 
68  std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
69 };
70 
71 class SpendingKeyEncoder : public boost::static_visitor<std::string>
72 {
73 private:
75 
76 public:
77  explicit SpendingKeyEncoder(const CChainParams& params) : m_params(params) {}
78 
79  std::string operator()(const libzcash::SaplingExtendedSpendingKey& zkey) const
80  {
81  CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
82  ss << zkey;
83  // ConvertBits requires unsigned char, but CDataStream uses char
84  std::vector<unsigned char> serkey(ss.begin(), ss.end());
85  std::vector<unsigned char> data;
86  // See calculation comment below
87  data.reserve((serkey.size() * 8 + 4) / 5);
88  ConvertBits<8, 5, true>([&](unsigned char c) { data.push_back(c); }, serkey.begin(), serkey.end());
90  memory_cleanse(serkey.data(), serkey.size());
91  memory_cleanse(data.data(), data.size());
92  return ret;
93  }
94 
95  std::string operator()(const libzcash::InvalidEncoding& no) const { return {}; }
96 };
97 
98 namespace KeyIO {
99 
100  // Sizes of SaplingPaymentAddress, SaplingExtendedFullViewingKey, and
101  // SaplingExtendedSpendingKey after ConvertBits<8, 5, true>(). The calculations
102  // below take the regular serialized size in bytes, convert to bits, and then
103  // perform ceiling division to get the number of 5-bit clusters.
104  const size_t ConvertedSaplingPaymentAddressSize = ((32 + 11) * 8 + 4) / 5;
107 
109  {
110  return boost::apply_visitor(PaymentAddressEncoder(Params()), zaddr);
111  }
112 
114  {
115  std::vector<unsigned char> data;
116  auto bech = bech32::Decode(str);
117  if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_PAYMENT_ADDRESS) &&
118  bech.second.size() == ConvertedSaplingPaymentAddressSize) {
119  // Bech32 decoding
120  data.reserve((bech.second.size() * 5) / 8);
121  if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) {
122  CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
124  ss >> ret;
125  return ret;
126  }
127  }
128  return libzcash::InvalidEncoding();
129  }
130 
132  {
134  const auto dest = boost::get<libzcash::SaplingPaymentAddress>(&addr);
135  return (dest) ? Optional<libzcash::SaplingPaymentAddress>(*dest) : nullopt;
136  }
137 
138  bool IsValidPaymentAddressString(const std::string& str) {
140  }
141 
142  std::string EncodeViewingKey(const libzcash::ViewingKey& vk)
143  {
144  return boost::apply_visitor(ViewingKeyEncoder(Params()), vk);
145  }
146 
147  libzcash::ViewingKey DecodeViewingKey(const std::string& str)
148  {
149  auto bech = bech32::Decode(str);
150  if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_FVK) &&
151  bech.second.size() == ConvertedSaplingExtendedFullViewingKeySize) {
152  std::vector<unsigned char> data;
153  // Bech32 decoding
154  data.reserve((bech.second.size() * 5) / 8);
155  if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) {
156  CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
158  ss >> ret;
159  memory_cleanse(data.data(), data.size());
160  return ret;
161  }
162  }
163  return libzcash::InvalidEncoding();
164  }
165 
166  std::string EncodeSpendingKey(const libzcash::SpendingKey& zkey)
167  {
168  return boost::apply_visitor(SpendingKeyEncoder(Params()), zkey);
169  }
170 
171  libzcash::SpendingKey DecodeSpendingKey(const std::string& str)
172  {
173  std::vector<unsigned char> data;
174  auto bech = bech32::Decode(str);
175  if (bech.first == Params().Bech32HRP(CChainParams::SAPLING_EXTENDED_SPEND_KEY) &&
176  bech.second.size() == ConvertedSaplingExtendedSpendingKeySize) {
177  // Bech32 decoding
178  data.reserve((bech.second.size() * 5) / 8);
179  if (ConvertBits<5, 8, false>([&](unsigned char c) { data.push_back(c); }, bech.second.begin(), bech.second.end())) {
180  CDataStream ss(data, SER_NETWORK, PROTOCOL_VERSION);
182  ss >> ret;
183  memory_cleanse(data.data(), data.size());
184  return ret;
185  }
186  }
187  memory_cleanse(data.data(), data.size());
188  return libzcash::InvalidEncoding();
189  }
190 
191 } // KeyIO namespace
bool IsValidPaymentAddress(const libzcash::PaymentAddress &zaddr)
Check whether a PaymentAddress is not an InvalidEncoding.
Definition: address.cpp:92
const CChainParams & Params()
Return the currently selected parameters.
const_iterator end() const
Definition: streams.h:163
const_iterator begin() const
Definition: streams.h:161
CChainParams defines various tweakable parameters of a given instance of the PIVX system.
Definition: chainparams.h:43
const std::string & Bech32HRP(Bech32Type type) const
Definition: chainparams.h:94
@ SAPLING_PAYMENT_ADDRESS
Definition: chainparams.h:60
@ SAPLING_EXTENDED_SPEND_KEY
Definition: chainparams.h:63
@ SAPLING_EXTENDED_FVK
Definition: chainparams.h:64
std::string operator()(const libzcash::SaplingPaymentAddress &zaddr) const
const CChainParams & m_params
std::string operator()(const libzcash::InvalidEncoding &no) const
PaymentAddressEncoder(const CChainParams &params)
std::string operator()(const libzcash::SaplingExtendedSpendingKey &zkey) const
std::string operator()(const libzcash::InvalidEncoding &no) const
SpendingKeyEncoder(const CChainParams &params)
const CChainParams & m_params
std::string operator()(const libzcash::SaplingExtendedFullViewingKey &extfvk) const
ViewingKeyEncoder(const CChainParams &params)
const CChainParams & m_params
std::string operator()(const libzcash::InvalidEncoding &no) const
Sapling functions.
Definition: address.h:30
void memory_cleanse(void *ptr, size_t len)
Definition: cleanse.cpp:27
libzcash::SpendingKey DecodeSpendingKey(const std::string &str)
std::string EncodePaymentAddress(const libzcash::PaymentAddress &zaddr)
const size_t ConvertedSaplingPaymentAddressSize
const size_t ConvertedSaplingExtendedFullViewingKeySize
Optional< libzcash::SaplingPaymentAddress > DecodeSaplingPaymentAddress(const std::string &strAddress)
libzcash::ViewingKey DecodeViewingKey(const std::string &str)
std::string EncodeViewingKey(const libzcash::ViewingKey &vk)
bool IsValidPaymentAddressString(const std::string &str)
libzcash::PaymentAddress DecodePaymentAddress(const std::string &str)
std::string EncodeSpendingKey(const libzcash::SpendingKey &zkey)
const size_t ConvertedSaplingExtendedSpendingKeySize
std::pair< std::string, data > Decode(const std::string &str)
Decode a Bech32 string.
Definition: bech32.cpp:158
std::string Encode(const std::string &hrp, const data &values)
Encode a Bech32 string.
Definition: bech32.cpp:143
boost::variant< InvalidEncoding, SaplingPaymentAddress > PaymentAddress
Definition: address.h:127
boost::variant< InvalidEncoding, SaplingExtendedSpendingKey > SpendingKey
Definition: zip32.h:116
boost::variant< InvalidEncoding, SaplingExtendedFullViewingKey > ViewingKey
Definition: zip32.h:117
boost::optional< T > Optional
Substitute for C++17 std::optional.
Definition: optional.h:12
@ SER_NETWORK
Definition: serialize.h:174
const size_t ZIP32_XFVK_SIZE
Definition: zip32.h:17
const size_t ZIP32_XSK_SIZE
Definition: zip32.h:18