1use core::convert::{TryFrom, TryInto};
8
9use dusk_bls12_381::BlsScalar;
10use dusk_bytes::{DeserializableSlice, Error as BytesError, Serializable};
11use dusk_jubjub::{GENERATOR_NUMS_EXTENDED, JubJubAffine, JubJubScalar, dhke};
12use dusk_poseidon::{Domain, Hash};
13use ff::Field;
14use jubjub_elgamal::{DecryptFrom, Encryption as ElGamal};
15use jubjub_schnorr::{PublicKey as NotePublicKey, SecretKey as NoteSecretKey};
16use rand::{CryptoRng, RngCore};
17
18use crate::{
19 Error, PublicKey, SecretKey, StealthAddress, ViewKey, aes,
20 transparent_value_commitment, value_commitment,
21};
22
23#[cfg(feature = "rkyv-impl")]
24use rkyv::{Archive, Deserialize, Serialize};
25
26pub(crate) const TRANSPARENT_BLINDER: JubJubScalar = JubJubScalar::zero();
28
29pub(crate) const PLAINTEXT_SIZE: usize = 40;
31
32pub const VALUE_ENC_SIZE: usize = PLAINTEXT_SIZE + aes::ENCRYPTION_EXTRA_SIZE;
34
35#[derive(Debug, Clone, Copy, Eq, PartialEq)]
37#[cfg_attr(
38 feature = "rkyv-impl",
39 derive(Archive, Serialize, Deserialize),
40 archive_attr(derive(bytecheck::CheckBytes))
41)]
42#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
43pub enum NoteType {
44 Transparent = 0,
46 Obfuscated = 1,
48}
49
50impl TryFrom<u8> for NoteType {
51 type Error = Error;
52
53 fn try_from(note_type: u8) -> Result<Self, Self::Error> {
54 match note_type {
55 0 => Ok(NoteType::Transparent),
56 1 => Ok(NoteType::Obfuscated),
57 n => Err(Error::InvalidNoteType(n)),
58 }
59 }
60}
61
62impl TryFrom<i32> for NoteType {
63 type Error = Error;
64
65 fn try_from(note_type: i32) -> Result<Self, Self::Error> {
66 (note_type as u8).try_into()
67 }
68}
69
70#[derive(Clone, Debug, Eq)]
72#[cfg_attr(
73 feature = "rkyv-impl",
74 derive(Archive, Serialize, Deserialize),
75 archive_attr(derive(bytecheck::CheckBytes))
76)]
77#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
78pub struct Note {
79 pub(crate) note_type: NoteType,
80 pub(crate) value_commitment: JubJubAffine,
81 pub(crate) stealth_address: StealthAddress,
82 #[cfg_attr(
83 feature = "serde",
84 serde(with = "serde_with::As::<serde_with::DisplayFromStr>")
85 )]
86 pub(crate) pos: u64,
87 #[cfg_attr(
88 feature = "serde",
89 serde(with = "serde_with::As::<serde_with::hex::Hex>")
90 )]
91 pub(crate) value_enc: [u8; VALUE_ENC_SIZE],
92 pub(crate) sender: Sender,
93}
94
95impl PartialEq for Note {
96 fn eq(&self, other: &Self) -> bool {
97 self.value_enc == other.value_enc
98 && self.sender == other.sender
99 && self.hash() == other.hash()
100 }
101}
102
103impl Note {
104 pub fn new<R: RngCore + CryptoRng>(
106 rng: &mut R,
107 note_type: NoteType,
108 sender_pk: &PublicKey,
109 receiver_pk: &PublicKey,
110 value: u64,
111 value_blinder: JubJubScalar,
112 sender_blinder: [JubJubScalar; 2],
113 ) -> Self {
114 let r = JubJubScalar::random(&mut *rng);
115 let stealth_address = receiver_pk.gen_stealth_address(&r);
116
117 let value_commitment = value_commitment(value, value_blinder);
118
119 let pos = u64::MAX;
121
122 let value_enc = match note_type {
123 NoteType::Transparent => {
124 let mut value_enc = [0u8; VALUE_ENC_SIZE];
125 value_enc[..u64::SIZE].copy_from_slice(&value.to_bytes());
126
127 value_enc
128 }
129 NoteType::Obfuscated => {
130 let shared_secret = dhke(&r, receiver_pk.A());
131 let value_blinder = BlsScalar::from(value_blinder);
132
133 let mut plaintext = value.to_bytes().to_vec();
134 plaintext.append(&mut value_blinder.to_bytes().to_vec());
135
136 let salt = stealth_address.to_bytes();
137
138 aes::encrypt(&shared_secret, &salt, &plaintext, rng)
139 .expect("Encrypted correctly.")
140 }
141 };
142
143 Note {
144 note_type,
145 value_commitment,
146 stealth_address,
147 pos,
148 value_enc,
149 sender: Sender::encrypt(
150 stealth_address.note_pk(),
151 sender_pk,
152 &sender_blinder,
153 ),
154 }
155 }
156
157 pub fn transparent<R: RngCore + CryptoRng>(
163 rng: &mut R,
164 sender_pk: &PublicKey,
165 receiver_pk: &PublicKey,
166 value: u64,
167 sender_blinder: [JubJubScalar; 2],
168 ) -> Self {
169 Self::new(
170 rng,
171 NoteType::Transparent,
172 sender_pk,
173 receiver_pk,
174 value,
175 TRANSPARENT_BLINDER,
176 sender_blinder,
177 )
178 }
179
180 pub fn transparent_stealth(
186 stealth_address: StealthAddress,
187 value: u64,
188 sender: impl Into<Sender>,
189 ) -> Self {
190 let value_commitment = transparent_value_commitment(value);
191
192 let pos = u64::MAX;
193
194 let mut value_enc = [0u8; VALUE_ENC_SIZE];
195 value_enc[..u64::SIZE].copy_from_slice(&value.to_bytes());
196
197 Note {
198 note_type: NoteType::Transparent,
199 value_commitment,
200 stealth_address,
201 pos,
202 value_enc,
203 sender: sender.into(),
204 }
205 }
206
207 pub fn obfuscated<R: RngCore + CryptoRng>(
214 rng: &mut R,
215 sender_pk: &PublicKey,
216 receiver_pk: &PublicKey,
217 value: u64,
218 value_blinder: JubJubScalar,
219 sender_blinder: [JubJubScalar; 2],
220 ) -> Self {
221 Self::new(
222 rng,
223 NoteType::Obfuscated,
224 sender_pk,
225 receiver_pk,
226 value,
227 value_blinder,
228 sender_blinder,
229 )
230 }
231
232 pub fn empty() -> Self {
234 Self {
235 note_type: NoteType::Transparent,
236 value_commitment: JubJubAffine::default(),
237 stealth_address: StealthAddress::default(),
238 pos: 0,
239 value_enc: [0; VALUE_ENC_SIZE],
240 sender: Sender::Encryption(
241 [(JubJubAffine::default(), JubJubAffine::default()); 2],
242 ),
243 }
244 }
245
246 fn decrypt_value(
247 &self,
248 vk: &ViewKey,
249 ) -> Result<(u64, JubJubScalar), Error> {
250 let R = self.stealth_address.R();
251 let shared_secret = dhke(vk.a(), R);
252
253 let salt = self.stealth_address.to_bytes();
254
255 let dec_plaintext: [u8; PLAINTEXT_SIZE] =
256 aes::decrypt(&shared_secret, &salt, &self.value_enc)?;
257
258 let value = u64::from_slice(&dec_plaintext[..u64::SIZE])?;
259
260 let value_blinder =
264 match JubJubScalar::from_slice(&dec_plaintext[u64::SIZE..])?.into()
265 {
266 Some(scalar) => scalar,
267 None => return Err(Error::InvalidData),
268 };
269
270 Ok((value, value_blinder))
271 }
272
273 pub fn gen_nullifier(&self, sk: &SecretKey) -> BlsScalar {
277 let note_sk = sk.gen_note_sk(&self.stealth_address);
278 let pk_prime = GENERATOR_NUMS_EXTENDED * note_sk.as_ref();
279 let pk_prime = pk_prime.to_hash_inputs();
280
281 let pos = BlsScalar::from(self.pos);
282
283 Hash::digest(Domain::Other, &[pk_prime[0], pk_prime[1], pos])[0]
284 }
285
286 pub fn hash_inputs(&self) -> [BlsScalar; 6] {
288 let note_pk =
289 self.stealth_address().note_pk().as_ref().to_hash_inputs();
290
291 [
292 BlsScalar::from(self.note_type as u64),
293 self.value_commitment.get_u(),
294 self.value_commitment.get_v(),
295 note_pk[0],
296 note_pk[1],
297 BlsScalar::from(self.pos),
298 ]
299 }
300
301 pub fn hash(&self) -> BlsScalar {
304 Hash::digest(Domain::Other, &self.hash_inputs())[0]
305 }
306
307 pub const fn note_type(&self) -> NoteType {
309 self.note_type
310 }
311
312 pub const fn pos(&self) -> &u64 {
314 &self.pos
315 }
316
317 pub const fn stealth_address(&self) -> &StealthAddress {
319 &self.stealth_address
320 }
321
322 pub fn set_pos(&mut self, pos: u64) {
325 self.pos = pos;
326 }
327
328 pub const fn value_commitment(&self) -> &JubJubAffine {
330 &self.value_commitment
331 }
332
333 pub const fn value_enc(&self) -> &[u8; VALUE_ENC_SIZE] {
335 &self.value_enc
336 }
337
338 pub const fn sender(&self) -> &Sender {
342 &self.sender
343 }
344
345 pub fn value(&self, vk: Option<&ViewKey>) -> Result<u64, Error> {
349 match (self.note_type, vk) {
350 (NoteType::Transparent, _) => {
351 let value =
352 u64::from_slice(&self.value_enc[..u64::SIZE]).unwrap();
353 Ok(value)
354 }
355 (NoteType::Obfuscated, Some(vk)) => {
356 self.decrypt_value(vk).map(|(value, _)| value)
357 }
358 _ => Err(Error::MissingViewKey),
359 }
360 }
361
362 pub fn value_blinder(
366 &self,
367 vk: Option<&ViewKey>,
368 ) -> Result<JubJubScalar, Error> {
369 match (self.note_type, vk) {
370 (NoteType::Transparent, _) => Ok(TRANSPARENT_BLINDER),
371 (NoteType::Obfuscated, Some(vk)) => self
372 .decrypt_value(vk)
373 .map(|(_, value_blinder)| value_blinder),
374 _ => Err(Error::MissingViewKey),
375 }
376 }
377}
378
379const SIZE: usize = 1
380 + JubJubAffine::SIZE
381 + StealthAddress::SIZE
382 + u64::SIZE
383 + VALUE_ENC_SIZE
384 + Sender::SIZE;
385
386impl Serializable<SIZE> for Note {
387 type Error = BytesError;
388
389 fn to_bytes(&self) -> [u8; Self::SIZE] {
391 let mut buf = [0u8; Self::SIZE];
392
393 buf[0] = self.note_type as u8;
394
395 let mut start = 1;
396
397 buf[start..start + JubJubAffine::SIZE]
398 .copy_from_slice(&self.value_commitment.to_bytes());
399 start += JubJubAffine::SIZE;
400
401 buf[start..start + StealthAddress::SIZE]
402 .copy_from_slice(&self.stealth_address.to_bytes());
403 start += StealthAddress::SIZE;
404
405 buf[start..start + u64::SIZE].copy_from_slice(&self.pos.to_le_bytes());
406 start += u64::SIZE;
407
408 buf[start..start + VALUE_ENC_SIZE].copy_from_slice(&self.value_enc);
409 start += VALUE_ENC_SIZE;
410
411 buf[start..start + Sender::SIZE]
412 .copy_from_slice(&self.sender.to_bytes());
413
414 buf
415 }
416
417 fn from_bytes(bytes: &[u8; Self::SIZE]) -> Result<Self, Self::Error> {
420 let note_type =
421 bytes[0].try_into().map_err(|_| BytesError::InvalidData)?;
422
423 let mut buf = &bytes[1..];
424
425 let value_commitment = JubJubAffine::from_reader(&mut buf)?;
426
427 let stealth_address = StealthAddress::from_reader(&mut buf)?;
428
429 let pos = u64::from_reader(&mut buf)?;
430
431 let mut value_enc = [0u8; VALUE_ENC_SIZE];
432 value_enc.copy_from_slice(&buf[..VALUE_ENC_SIZE]);
433 buf = &buf[VALUE_ENC_SIZE..];
434
435 let sender = Sender::from_reader(&mut buf)?;
436
437 Ok(Note {
438 note_type,
439 value_commitment,
440 stealth_address,
441 pos,
442 value_enc,
443 sender,
444 })
445 }
446}
447
448#[derive(Copy, Clone, Debug, PartialEq, Eq)]
454#[cfg_attr(
455 feature = "rkyv-impl",
456 derive(Archive, Serialize, Deserialize),
457 archive_attr(derive(bytecheck::CheckBytes))
458)]
459#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
460pub enum Sender {
461 Encryption([(JubJubAffine, JubJubAffine); 2]),
464 ContractInfo(
467 #[cfg_attr(
468 feature = "serde",
469 serde(with = "serde_with::As::<serde_with::hex::Hex>")
470 )]
471 [u8; 4 * JubJubAffine::SIZE],
472 ),
473}
474
475impl Sender {
476 pub fn encrypt(
479 note_pk: &NotePublicKey,
480 sender_pk: &PublicKey,
481 blinder: &[JubJubScalar; 2],
482 ) -> Self {
483 let (sender_enc_A, _) = ElGamal::encrypt(
484 note_pk.as_ref(),
485 sender_pk.A(),
486 None,
487 &blinder[0],
488 );
489
490 let (sender_enc_B, _) = ElGamal::encrypt(
491 note_pk.as_ref(),
492 sender_pk.B(),
493 None,
494 &blinder[1],
495 );
496
497 let sender_enc_A: (JubJubAffine, JubJubAffine) =
498 (sender_enc_A.c1().into(), sender_enc_A.c2().into());
499 let sender_enc_B: (JubJubAffine, JubJubAffine) =
500 (sender_enc_B.c1().into(), sender_enc_B.c2().into());
501
502 Self::Encryption([sender_enc_A, sender_enc_B])
503 }
504
505 pub fn decrypt(&self, note_sk: &NoteSecretKey) -> Result<PublicKey, Error> {
515 let sender_enc = match self {
516 Sender::Encryption(enc) => enc,
517 Sender::ContractInfo(_) => {
518 return Err(Error::InvalidEncryption);
519 }
520 };
521
522 let sender_enc_A =
523 ElGamal::new(sender_enc[0].0.into(), sender_enc[0].1.into())
524 .map_err(|_| Error::InvalidEncryption)?;
525 let sender_enc_B =
526 ElGamal::new(sender_enc[1].0.into(), sender_enc[1].1.into())
527 .map_err(|_| Error::InvalidEncryption)?;
528
529 let decrypt_A =
530 sender_enc_A.decrypt(&DecryptFrom::SecretKey(*note_sk.as_ref()));
531 let decrypt_B =
532 sender_enc_B.decrypt(&DecryptFrom::SecretKey(*note_sk.as_ref()));
533
534 Ok(PublicKey::new(decrypt_A, decrypt_B))
535 }
536}
537
538impl Serializable<{ 1 + 4 * JubJubAffine::SIZE }> for Sender {
539 type Error = BytesError;
540
541 fn to_bytes(&self) -> [u8; Self::SIZE] {
543 let mut buf = [0u8; Self::SIZE];
544
545 match self {
546 Sender::Encryption(sender_enc) => {
547 buf[0] = 0;
548 let mut start = 1;
549
550 buf[start..start + JubJubAffine::SIZE]
551 .copy_from_slice(&sender_enc[0].0.to_bytes());
552 start += JubJubAffine::SIZE;
553
554 buf[start..start + JubJubAffine::SIZE]
555 .copy_from_slice(&sender_enc[0].1.to_bytes());
556 start += JubJubAffine::SIZE;
557
558 buf[start..start + JubJubAffine::SIZE]
559 .copy_from_slice(&sender_enc[1].0.to_bytes());
560 start += JubJubAffine::SIZE;
561
562 buf[start..start + JubJubAffine::SIZE]
563 .copy_from_slice(&sender_enc[1].1.to_bytes());
564 }
565 Sender::ContractInfo(contract_data) => {
566 buf[0] = 1;
567 buf[1..].copy_from_slice(&contract_data[..]);
568 }
569 }
570
571 buf
572 }
573
574 fn from_bytes(bytes: &[u8; Self::SIZE]) -> Result<Self, Self::Error> {
577 let sender = match bytes[0] {
578 0 => {
579 let mut buf = &bytes[1..];
580 let sender_enc_A_0 = JubJubAffine::from_reader(&mut buf)?;
581 let sender_enc_A_1 = JubJubAffine::from_reader(&mut buf)?;
582 let sender_enc_B_0 = JubJubAffine::from_reader(&mut buf)?;
583 let sender_enc_B_1 = JubJubAffine::from_reader(&mut buf)?;
584 Sender::Encryption([
585 (sender_enc_A_0, sender_enc_A_1),
586 (sender_enc_B_0, sender_enc_B_1),
587 ])
588 }
589 1 => {
590 let mut contract_data = [0u8; 4 * JubJubAffine::SIZE];
591 contract_data.copy_from_slice(&bytes[1..Self::SIZE]);
592 Sender::ContractInfo(contract_data)
593 }
594 _ => return Err(BytesError::InvalidData),
595 };
596
597 Ok(sender)
598 }
599}