snarkvm_circuit_program/data/record/
mod.rs1#[cfg(test)]
17use snarkvm_circuit_types::environment::assert_scope;
18
19mod entry;
20pub use entry::Entry;
21
22mod helpers;
23pub use helpers::Owner;
24
25mod decrypt;
26mod encrypt;
27mod equal;
28mod find;
29mod num_randomizers;
30mod serial_number;
31mod tag;
32mod to_bits;
33mod to_commitment;
34mod to_fields;
35
36use crate::{Access, Ciphertext, Identifier, Literal, Plaintext, ProgramID, Visibility};
37use snarkvm_circuit_account::{PrivateKey, ViewKey};
38use snarkvm_circuit_network::Aleo;
39use snarkvm_circuit_types::{Boolean, Field, Group, Scalar, U8, U32, environment::prelude::*};
40
41#[derive(Clone)]
42pub struct Record<A: Aleo, Private: Visibility<A>> {
43 owner: Owner<A, Private>,
45 data: IndexMap<Identifier<A>, Entry<A, Private>>,
47 nonce: Group<A>,
49 version: U8<A>,
53}
54
55impl<A: Aleo> Inject for Record<A, Plaintext<A>> {
56 type Primitive = console::Record<A::Network, console::Plaintext<A::Network>>;
57
58 fn new(_: Mode, record: Self::Primitive) -> Self {
60 Self {
61 owner: Owner::new(Mode::Private, record.owner().clone()),
62 data: Inject::new(Mode::Private, record.data().clone()),
63 nonce: Group::new(Mode::Private, *record.nonce()),
64 version: U8::new(Mode::Private, *record.version()),
65 }
66 }
67}
68
69impl<A: Aleo> Inject for Record<A, Ciphertext<A>> {
70 type Primitive = console::Record<A::Network, console::Ciphertext<A::Network>>;
71
72 fn new(_: Mode, record: Self::Primitive) -> Self {
74 Self {
75 owner: Owner::new(Mode::Private, record.owner().clone()),
76 data: Inject::new(Mode::Private, record.data().clone()),
77 nonce: Group::new(Mode::Private, *record.nonce()),
78 version: U8::new(Mode::Private, *record.version()),
79 }
80 }
81}
82
83impl<A: Aleo, Private: Visibility<A>> Record<A, Private> {
84 pub fn from_plaintext(
86 owner: Owner<A, Plaintext<A>>,
87 data: IndexMap<Identifier<A>, Entry<A, Plaintext<A>>>,
88 nonce: Group<A>,
89 version: U8<A>,
90 ) -> Result<Record<A, Plaintext<A>>> {
91 ensure!(!has_duplicates(data.iter().map(|(name, ..)| name)), "A duplicate entry name was found in a record");
93 ensure!(
95 data.len() <= <A::Network as console::Network>::MAX_DATA_ENTRIES,
96 "Found a record that exceeds size ({})",
97 data.len()
98 );
99 Ok(Record { owner, data, nonce, version })
101 }
102
103 pub fn from_ciphertext(
105 owner: Owner<A, Ciphertext<A>>,
106 data: IndexMap<Identifier<A>, Entry<A, Ciphertext<A>>>,
107 nonce: Group<A>,
108 version: U8<A>,
109 ) -> Result<Record<A, Ciphertext<A>>> {
110 ensure!(!has_duplicates(data.iter().map(|(name, ..)| name)), "A duplicate entry name was found in a record");
112 ensure!(
114 data.len() <= <A::Network as console::Network>::MAX_DATA_ENTRIES,
115 "Found a record that exceeds size ({})",
116 data.len()
117 );
118 Ok(Record { owner, data, nonce, version })
120 }
121}
122
123impl<A: Aleo, Private: Visibility<A>> Record<A, Private> {
124 pub const fn owner(&self) -> &Owner<A, Private> {
126 &self.owner
127 }
128
129 pub const fn data(&self) -> &IndexMap<Identifier<A>, Entry<A, Private>> {
131 &self.data
132 }
133
134 pub const fn nonce(&self) -> &Group<A> {
136 &self.nonce
137 }
138
139 pub const fn version(&self) -> &U8<A> {
141 &self.version
142 }
143
144 pub fn is_hiding(&self) -> Boolean<A> {
146 !self.version.is_zero()
147 }
148}
149
150impl<A: Aleo> Eject for Record<A, Plaintext<A>> {
151 type Primitive = console::Record<A::Network, console::Plaintext<A::Network>>;
152
153 fn eject_mode(&self) -> Mode {
155 let owner = match &self.owner {
156 Owner::Public(owner) => match owner.eject_mode() == Mode::Public {
157 true => Mode::Public,
158 false => A::halt("Record::<Plaintext>::eject_mode: 'owner' is not public."),
159 },
160 Owner::Private(plaintext) => match plaintext.eject_mode() == Mode::Private {
161 true => Mode::Private,
162 false => A::halt("Record::<Plaintext>::eject_mode: 'owner' is not private."),
163 },
164 };
165
166 let data = self.data.iter().map(|(_, entry)| entry.eject_mode()).collect::<Vec<_>>().eject_mode();
167 let nonce = self.nonce.eject_mode();
168 let version = self.version.eject_mode();
169
170 Mode::combine(owner, [data, nonce, version])
171 }
172
173 fn eject_value(&self) -> Self::Primitive {
175 let owner = match &self.owner {
176 Owner::Public(owner) => console::Owner::Public(owner.eject_value()),
177 Owner::Private(plaintext) => console::Owner::Private(plaintext.eject_value()),
178 };
179
180 match Self::Primitive::from_plaintext(
181 owner,
182 self.data.iter().map(|(identifier, entry)| (identifier, entry).eject_value()).collect::<IndexMap<_, _>>(),
183 self.nonce.eject_value(),
184 self.version.eject_value(),
185 ) {
186 Ok(record) => record,
187 Err(error) => A::halt(format!("Record::<Plaintext>::eject_value: {error}")),
188 }
189 }
190}
191
192impl<A: Aleo> Eject for Record<A, Ciphertext<A>> {
193 type Primitive = console::Record<A::Network, console::Ciphertext<A::Network>>;
194
195 fn eject_mode(&self) -> Mode {
197 let owner = match &self.owner {
198 Owner::Public(owner) => match owner.eject_mode() == Mode::Public {
199 true => Mode::Public,
200 false => A::halt("Record::<Ciphertext>::eject_mode: 'owner' is not public."),
201 },
202 Owner::Private(plaintext) => match plaintext.eject_mode() == Mode::Private {
203 true => Mode::Private,
204 false => A::halt("Record::<Ciphertext>::eject_mode: 'owner' is not private."),
205 },
206 };
207
208 let data = self.data.iter().map(|(_, entry)| entry.eject_mode()).collect::<Vec<_>>().eject_mode();
209 let nonce = self.nonce.eject_mode();
210 let version = self.version.eject_mode();
211
212 Mode::combine(owner, [data, nonce, version])
213 }
214
215 fn eject_value(&self) -> Self::Primitive {
217 let owner = match &self.owner {
218 Owner::Public(owner) => console::Owner::Public(owner.eject_value()),
219 Owner::Private(plaintext) => console::Owner::Private(plaintext.eject_value()),
220 };
221
222 match Self::Primitive::from_ciphertext(
223 owner,
224 self.data.iter().map(|(identifier, entry)| (identifier, entry).eject_value()).collect::<IndexMap<_, _>>(),
225 self.nonce.eject_value(),
226 self.version.eject_value(),
227 ) {
228 Ok(record) => record,
229 Err(error) => A::halt(format!("Record::<Ciphertext>::eject_value: {error}")),
230 }
231 }
232}
233
234impl<A: Aleo, Private: Visibility<A>> TypeName for Record<A, Private> {
235 fn type_name() -> &'static str {
236 "record"
237 }
238}