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::*, prelude::ToFields};
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: record
63 .data()
64 .clone()
65 .into_iter()
66 .map(|(identifier, entry)| (Identifier::constant(identifier), Inject::new(Mode::Private, entry)))
67 .collect(),
68 nonce: Group::new(Mode::Private, *record.nonce()),
69 version: U8::new(Mode::Private, *record.version()),
70 }
71 }
72}
73
74impl<A: Aleo> Inject for Record<A, Ciphertext<A>> {
75 type Primitive = console::Record<A::Network, console::Ciphertext<A::Network>>;
76
77 fn new(_: Mode, record: Self::Primitive) -> Self {
79 Self {
80 owner: Owner::new(Mode::Private, record.owner().clone()),
81 data: record
82 .data()
83 .clone()
84 .into_iter()
85 .map(|(identifier, entry)| (Identifier::constant(identifier), Inject::new(Mode::Private, entry)))
86 .collect(),
87 nonce: Group::new(Mode::Private, *record.nonce()),
88 version: U8::new(Mode::Private, *record.version()),
89 }
90 }
91}
92
93impl<A: Aleo, Private: Visibility<A>> Record<A, Private> {
94 pub fn from_plaintext(
96 owner: Owner<A, Plaintext<A>>,
97 data: IndexMap<Identifier<A>, Entry<A, Plaintext<A>>>,
98 nonce: Group<A>,
99 version: U8<A>,
100 ) -> Result<Record<A, Plaintext<A>>> {
101 ensure!(!has_duplicates(data.iter().map(|(name, ..)| name)), "A duplicate entry name was found in a record");
103 ensure!(
105 data.len() <= <A::Network as console::Network>::MAX_DATA_ENTRIES,
106 "Found a record that exceeds size ({})",
107 data.len()
108 );
109 Ok(Record { owner, data, nonce, version })
111 }
112
113 pub fn from_ciphertext(
115 owner: Owner<A, Ciphertext<A>>,
116 data: IndexMap<Identifier<A>, Entry<A, Ciphertext<A>>>,
117 nonce: Group<A>,
118 version: U8<A>,
119 ) -> Result<Record<A, Ciphertext<A>>> {
120 ensure!(!has_duplicates(data.iter().map(|(name, ..)| name)), "A duplicate entry name was found in a record");
122 ensure!(
124 data.len() <= <A::Network as console::Network>::MAX_DATA_ENTRIES,
125 "Found a record that exceeds size ({})",
126 data.len()
127 );
128 Ok(Record { owner, data, nonce, version })
130 }
131}
132
133impl<A: Aleo, Private: Visibility<A>> Record<A, Private> {
134 pub const fn owner(&self) -> &Owner<A, Private> {
136 &self.owner
137 }
138
139 pub const fn data(&self) -> &IndexMap<Identifier<A>, Entry<A, Private>> {
141 &self.data
142 }
143
144 pub const fn nonce(&self) -> &Group<A> {
146 &self.nonce
147 }
148
149 pub const fn version(&self) -> &U8<A> {
151 &self.version
152 }
153
154 pub fn is_hiding(&self) -> Boolean<A> {
156 !self.version.is_zero()
157 }
158}
159
160impl<A: Aleo> Eject for Record<A, Plaintext<A>> {
161 type Primitive = console::Record<A::Network, console::Plaintext<A::Network>>;
162
163 fn eject_mode(&self) -> Mode {
165 let owner = match &self.owner {
166 Owner::Public(owner) => match owner.eject_mode() == Mode::Public {
167 true => Mode::Public,
168 false => A::halt("Record::<Plaintext>::eject_mode: 'owner' is not public."),
169 },
170 Owner::Private(plaintext) => match plaintext.eject_mode() == Mode::Private {
171 true => Mode::Private,
172 false => A::halt("Record::<Plaintext>::eject_mode: 'owner' is not private."),
173 },
174 };
175
176 let data = self.data.iter().map(|(_, entry)| entry.eject_mode()).collect::<Vec<_>>().eject_mode();
177 let nonce = self.nonce.eject_mode();
178 let version = self.version.eject_mode();
179
180 Mode::combine(owner, [data, nonce, version])
181 }
182
183 fn eject_value(&self) -> Self::Primitive {
185 let owner = match &self.owner {
186 Owner::Public(owner) => console::Owner::Public(owner.eject_value()),
187 Owner::Private(plaintext) => console::Owner::Private(plaintext.eject_value()),
188 };
189
190 match Self::Primitive::from_plaintext(
191 owner,
192 self.data.iter().map(|(identifier, entry)| (identifier, entry).eject_value()).collect::<IndexMap<_, _>>(),
193 self.nonce.eject_value(),
194 self.version.eject_value(),
195 ) {
196 Ok(record) => record,
197 Err(error) => A::halt(format!("Record::<Plaintext>::eject_value: {error}")),
198 }
199 }
200}
201
202impl<A: Aleo> Eject for Record<A, Ciphertext<A>> {
203 type Primitive = console::Record<A::Network, console::Ciphertext<A::Network>>;
204
205 fn eject_mode(&self) -> Mode {
207 let owner = match &self.owner {
208 Owner::Public(owner) => match owner.eject_mode() == Mode::Public {
209 true => Mode::Public,
210 false => A::halt("Record::<Ciphertext>::eject_mode: 'owner' is not public."),
211 },
212 Owner::Private(plaintext) => match plaintext.eject_mode() == Mode::Private {
213 true => Mode::Private,
214 false => A::halt("Record::<Ciphertext>::eject_mode: 'owner' is not private."),
215 },
216 };
217
218 let data = self.data.iter().map(|(_, entry)| entry.eject_mode()).collect::<Vec<_>>().eject_mode();
219 let nonce = self.nonce.eject_mode();
220 let version = self.version.eject_mode();
221
222 Mode::combine(owner, [data, nonce, version])
223 }
224
225 fn eject_value(&self) -> Self::Primitive {
227 let owner = match &self.owner {
228 Owner::Public(owner) => console::Owner::Public(owner.eject_value()),
229 Owner::Private(plaintext) => console::Owner::Private(plaintext.eject_value()),
230 };
231
232 match Self::Primitive::from_ciphertext(
233 owner,
234 self.data.iter().map(|(identifier, entry)| (identifier, entry).eject_value()).collect::<IndexMap<_, _>>(),
235 self.nonce.eject_value(),
236 self.version.eject_value(),
237 ) {
238 Ok(record) => record,
239 Err(error) => A::halt(format!("Record::<Ciphertext>::eject_value: {error}")),
240 }
241 }
242}
243
244impl<A: Aleo, Private: Visibility<A>> TypeName for Record<A, Private> {
245 fn type_name() -> &'static str {
246 "record"
247 }
248}