zebra_chain/orchard/
note.rs1use group::{ff::PrimeField, GroupEncoding};
4use halo2::pasta::pallas;
5use rand_core::{CryptoRng, RngCore};
6
7use crate::{
8 amount::{Amount, NonNegative},
9 error::{NoteError, RandError},
10};
11
12use super::{address::Address, sinsemilla::extract_p};
13
14mod ciphertexts;
15mod nullifiers;
16
17pub use ciphertexts::{EncryptedNote, WrappedNoteKey};
18pub use nullifiers::Nullifier;
19
20#[cfg(any(test, feature = "proptest-impl"))]
21mod arbitrary;
22
23#[derive(Clone, Copy, Debug)]
25#[allow(dead_code)]
30pub struct SeedRandomness(pub(crate) [u8; 32]);
31
32impl SeedRandomness {
33 pub fn new<T>(csprng: &mut T) -> Result<Self, RandError>
34 where
35 T: RngCore + CryptoRng,
36 {
37 let mut bytes = [0u8; 32];
38 csprng
39 .try_fill_bytes(&mut bytes)
40 .map_err(|_| RandError::FillBytes)?;
41 Ok(Self(bytes))
42 }
43}
44
45#[derive(Clone, Debug)]
55pub struct Rho(pub(crate) pallas::Base);
56
57impl From<Rho> for [u8; 32] {
58 fn from(rho: Rho) -> Self {
59 rho.0.to_repr()
60 }
61}
62
63impl From<Nullifier> for Rho {
64 fn from(nf: Nullifier) -> Self {
65 Self(nf.0)
66 }
67}
68
69impl Rho {
70 pub fn new<T>(csprng: &mut T) -> Result<Self, NoteError>
71 where
72 T: RngCore + CryptoRng,
73 {
74 let mut bytes = [0u8; 32];
75 csprng
76 .try_fill_bytes(&mut bytes)
77 .map_err(|_| NoteError::from(RandError::FillBytes))?;
78
79 let possible_point = pallas::Point::from_bytes(&bytes);
80
81 if possible_point.is_some().into() {
82 Ok(Self(extract_p(possible_point.unwrap())))
83 } else {
84 Err(NoteError::InvalidRho)
85 }
86 }
87}
88
89#[derive(Clone, Debug)]
93pub struct Psi(pub(crate) pallas::Base);
94
95impl From<Psi> for [u8; 32] {
96 fn from(psi: Psi) -> Self {
97 psi.0.to_repr()
98 }
99}
100
101#[derive(Clone, Debug)]
106pub struct Note {
107 pub address: Address,
109 pub value: Amount<NonNegative>,
111 pub rho: Rho,
114 pub rseed: SeedRandomness,
117}
118
119impl Note {
120 pub fn new<T>(
125 csprng: &mut T,
126 address: Address,
127 value: Amount<NonNegative>,
128 nf_old: Nullifier,
129 ) -> Result<Self, RandError>
130 where
131 T: RngCore + CryptoRng,
132 {
133 Ok(Self {
134 address,
135 value,
136 rho: nf_old.into(),
137 rseed: SeedRandomness::new(csprng)?,
138 })
139 }
140}