PIVX Core  5.6.99
P2P Digital Currency
note.cpp
Go to the documentation of this file.
1 // Copyright (c) 2016-2020 The ZCash developers
2 // Copyright (c) 2021 The PIVX Core developers
3 // Distributed under the MIT software license, see the accompanying
4 // file COPYING or https://www.opensource.org/licenses/mit-license.php.
5 
6 #include "sapling/note.h"
7 
8 #include "crypto/sha256.h"
9 #include "random.h"
10 #include "sapling/prf.h"
11 #include "sapling/sapling_util.h"
12 #include "streams.h"
13 #include "version.h"
14 
15 #include <librustzcash.h>
16 
17 using namespace libzcash;
18 
19 // Construct and populate Sapling note for a given payment address and value.
20 SaplingNote::SaplingNote(const SaplingPaymentAddress& address, const uint64_t value) :
21  BaseNote(value)
22 {
23  d = address.d;
24  pk_d = address.pk_d;
26 }
27 
28 // Call librustzcash to compute the commitment
30 {
31  uint256 result;
33  d.data(),
34  pk_d.begin(),
35  value(),
36  r.begin(),
37  result.begin()
38  ))
39  {
40  return nullopt;
41  }
42 
43  return result;
44 }
45 
46 // Call librustzcash to compute the nullifier
47 Optional<uint256> SaplingNote::nullifier(const SaplingFullViewingKey& vk, const uint64_t position) const
48 {
49  auto ak = vk.ak;
50  auto nk = vk.nk;
51 
52  uint256 result;
54  d.data(),
55  pk_d.begin(),
56  value(),
57  r.begin(),
58  ak.begin(),
59  nk.begin(),
60  position,
61  result.begin()
62  ))
63  {
64  return nullopt;
65  }
66 
67  return result;
68 }
69 
70 // Construct and populate SaplingNotePlaintext for a given note and memo.
72  const SaplingNote& note,
73  const std::array<unsigned char, ZC_MEMO_SIZE>& memo) : BaseNotePlaintext(note, memo)
74 {
75  d = note.d;
76  rcm = note.r;
77 }
78 
79 
81 {
82  auto addr = ivk.address(d);
83  if (addr) {
84  return SaplingNote(d, addr.get().pk_d, value_, rcm);
85  } else {
86  return nullopt;
87  }
88 }
89 
91  const SaplingOutCiphertext& ciphertext,
92  const uint256& ovk,
93  const uint256& cv,
94  const uint256& cm,
95  const uint256& epk
96 )
97 {
98  auto pt = AttemptSaplingOutDecryption(ciphertext, ovk, cv, cm, epk);
99  if (!pt) {
100  return nullopt;
101  }
102 
103  // Deserialize from the plaintext
104  CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
105  ss << pt.get();
106 
108  ss >> ret;
109 
110  assert(ss.size() == 0);
111 
112  return ret;
113 }
114 
116  const SaplingEncCiphertext& ciphertext,
117  const uint256& ivk,
118  const uint256& epk,
119  const uint256& cmu
120 )
121 {
122  auto pt = AttemptSaplingEncDecryption(ciphertext, ivk, epk);
123  if (!pt) {
124  return nullopt;
125  }
126 
127  // Deserialize from the plaintext
128  CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
129  ss << pt.get();
130 
132  ss >> ret;
133 
134  assert(ss.size() == 0);
135 
136  uint256 pk_d;
137  if (!librustzcash_ivk_to_pkd(ivk.begin(), ret.d.data(), pk_d.begin())) {
138  return nullopt;
139  }
140 
141  uint256 cmu_expected;
143  ret.d.data(),
144  pk_d.begin(),
145  ret.value(),
146  ret.rcm.begin(),
147  cmu_expected.begin()
148  ))
149  {
150  return nullopt;
151  }
152 
153  if (cmu_expected != cmu) {
154  return nullopt;
155  }
156 
157  return ret;
158 }
159 
161  const SaplingEncCiphertext& ciphertext,
162  const uint256& epk,
163  const uint256& esk,
164  const uint256& pk_d,
165  const uint256& cmu
166 )
167 {
168  auto pt = AttemptSaplingEncDecryption(ciphertext, epk, esk, pk_d);
169  if (!pt) {
170  return nullopt;
171  }
172 
173  // Deserialize from the plaintext
174  CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
175  ss << pt.get();
176 
178  ss >> ret;
179 
180  uint256 cmu_expected;
182  ret.d.data(),
183  pk_d.begin(),
184  ret.value(),
185  ret.rcm.begin(),
186  cmu_expected.begin()
187  ))
188  {
189  return nullopt;
190  }
191 
192  if (cmu_expected != cmu) {
193  return nullopt;
194  }
195 
196  assert(ss.size() == 0);
197 
198  return ret;
199 }
200 
202 {
203  // Get the encryptor
205  if (!sne) {
206  return nullopt;
207  }
208  auto enc = sne.get();
209 
210  // Create the plaintext
211  CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
212  ss << (*this);
214  assert(pt.size() == ss.size());
215  memcpy(&pt[0], &ss[0], pt.size());
216 
217  // Encrypt the plaintext
218  auto encciphertext = enc.encrypt_to_recipient(pk_d, pt);
219  if (!encciphertext) {
220  return nullopt;
221  }
222  return SaplingNotePlaintextEncryptionResult(encciphertext.get(), enc);
223 }
224 
225 
227  const uint256& ovk,
228  const uint256& cv,
229  const uint256& cm,
231  ) const
232 {
233  // Create the plaintext
234  CDataStream ss(SER_NETWORK, PROTOCOL_VERSION);
235  ss << (*this);
237  assert(pt.size() == ss.size());
238  memcpy(&pt[0], &ss[0], pt.size());
239 
240  return enc.encrypt_to_ourselves(ovk, cv, cm, pt);
241 }
size_type size() const
Definition: streams.h:165
unsigned char * begin()
Definition: uint256.h:63
Notes are main primitive of Sapling, similar to a a tree of commitments.
Definition: note.h:22
uint64_t value() const
Definition: note.h:30
uint64_t value() const
Definition: note.h:65
Optional< SaplingPaymentAddress > address(diversifier_t d) const
Definition: address.cpp:73
This is not a thread-safe API.
SaplingOutCiphertext encrypt_to_ourselves(const uint256 &ovk, const uint256 &cv, const uint256 &cm, const SaplingOutPlaintext &message)
static Optional< SaplingNoteEncryption > FromDiversifier(diversifier_t d)
Optional< uint256 > cmu() const
Definition: note.cpp:29
diversifier_t d
Definition: note.h:35
uint256 pk_d
Definition: note.h:36
Optional< uint256 > nullifier(const SaplingFullViewingKey &vk, const uint64_t position) const
Definition: note.cpp:47
Optional< SaplingNote > note(const SaplingIncomingViewingKey &ivk) const
Definition: note.cpp:80
Optional< SaplingNotePlaintextEncryptionResult > encrypt(const uint256 &pk_d) const
Definition: note.cpp:201
static Optional< SaplingNotePlaintext > decrypt(const SaplingEncCiphertext &ciphertext, const uint256 &ivk, const uint256 &epk, const uint256 &cmu)
Definition: note.cpp:115
SaplingOutCiphertext encrypt(const uint256 &ovk, const uint256 &cv, const uint256 &cm, SaplingNoteEncryption &enc) const
Definition: note.cpp:226
static Optional< SaplingOutgoingPlaintext > decrypt(const SaplingOutCiphertext &ciphertext, const uint256 &ovk, const uint256 &cv, const uint256 &cm, const uint256 &epk)
Definition: note.cpp:90
Sapling functions.
Definition: address.h:30
256-bit opaque blob.
Definition: uint256.h:138
void * memcpy(void *a, const void *b, size_t c)
bool librustzcash_sapling_compute_cm(const unsigned char *diversifier, const unsigned char *pk_d, const uint64_t value, const unsigned char *r, unsigned char *result)
Compute a Sapling commitment.
void librustzcash_sapling_generate_r(unsigned char *result)
Generate uniformly random scalar in Jubjub.
bool librustzcash_sapling_compute_nf(const unsigned char *diversifier, const unsigned char *pk_d, const uint64_t value, const unsigned char *r, const unsigned char *ak, const unsigned char *nk, const uint64_t position, unsigned char *result)
Compute a Sapling nullifier.
bool librustzcash_ivk_to_pkd(const unsigned char *ivk, const unsigned char *diversifier, unsigned char *result)
std::array< unsigned char, ZC_SAPLING_ENCPLAINTEXT_SIZE > SaplingEncPlaintext
Optional< SaplingEncPlaintext > AttemptSaplingEncDecryption(const SaplingEncCiphertext &ciphertext, const uint256 &ivk, const uint256 &epk)
std::array< unsigned char, ZC_SAPLING_OUTPLAINTEXT_SIZE > SaplingOutPlaintext
std::array< unsigned char, ZC_SAPLING_ENCCIPHERTEXT_SIZE > SaplingEncCiphertext
std::pair< SaplingEncCiphertext, SaplingNoteEncryption > SaplingNotePlaintextEncryptionResult
Definition: note.h:69
Optional< SaplingOutPlaintext > AttemptSaplingOutDecryption(const SaplingOutCiphertext &ciphertext, const uint256 &ovk, const uint256 &cv, const uint256 &cm, const uint256 &epk)
std::array< unsigned char, ZC_SAPLING_OUTCIPHERTEXT_SIZE > SaplingOutCiphertext
boost::optional< T > Optional
Substitute for C++17 std::optional.
Definition: optional.h:12
@ SER_NETWORK
Definition: serialize.h:174