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, Plaintext, ProgramID, Visibility};
37use snarkvm_circuit_account::{PrivateKey, ViewKey};
38use snarkvm_circuit_network::Aleo;
39use snarkvm_circuit_types::{Boolean, Field, Group, Scalar, 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}
50
51#[cfg(feature = "console")]
52impl<A: Aleo> Inject for Record<A, Plaintext<A>> {
53 type Primitive = console::Record<A::Network, console::Plaintext<A::Network>>;
54
55 fn new(_: Mode, record: Self::Primitive) -> Self {
57 Self {
58 owner: Owner::new(Mode::Private, record.owner().clone()),
59 data: Inject::new(Mode::Private, record.data().clone()),
60 nonce: Group::new(Mode::Private, *record.nonce()),
61 }
62 }
63}
64
65#[cfg(feature = "console")]
66impl<A: Aleo> Inject for Record<A, Ciphertext<A>> {
67 type Primitive = console::Record<A::Network, console::Ciphertext<A::Network>>;
68
69 fn new(_: Mode, record: Self::Primitive) -> Self {
71 Self {
72 owner: Owner::new(Mode::Private, record.owner().clone()),
73 data: Inject::new(Mode::Private, record.data().clone()),
74 nonce: Group::new(Mode::Private, *record.nonce()),
75 }
76 }
77}
78
79#[cfg(feature = "console")]
80impl<A: Aleo, Private: Visibility<A>> Record<A, Private> {
81 pub fn from_plaintext(
83 owner: Owner<A, Plaintext<A>>,
84 data: IndexMap<Identifier<A>, Entry<A, Plaintext<A>>>,
85 nonce: Group<A>,
86 ) -> Result<Record<A, Plaintext<A>>> {
87 ensure!(!has_duplicates(data.iter().map(|(name, ..)| name)), "A duplicate entry name was found in a record");
89 ensure!(
91 data.len() <= <A::Network as console::Network>::MAX_DATA_ENTRIES,
92 "Found a record that exceeds size ({})",
93 data.len()
94 );
95 Ok(Record { owner, data, nonce })
97 }
98
99 pub fn from_ciphertext(
101 owner: Owner<A, Ciphertext<A>>,
102 data: IndexMap<Identifier<A>, Entry<A, Ciphertext<A>>>,
103 nonce: Group<A>,
104 ) -> Result<Record<A, Ciphertext<A>>> {
105 ensure!(!has_duplicates(data.iter().map(|(name, ..)| name)), "A duplicate entry name was found in a record");
107 ensure!(
109 data.len() <= <A::Network as console::Network>::MAX_DATA_ENTRIES,
110 "Found a record that exceeds size ({})",
111 data.len()
112 );
113 Ok(Record { owner, data, nonce })
115 }
116}
117
118impl<A: Aleo, Private: Visibility<A>> Record<A, Private> {
119 pub const fn owner(&self) -> &Owner<A, Private> {
121 &self.owner
122 }
123
124 pub const fn data(&self) -> &IndexMap<Identifier<A>, Entry<A, Private>> {
126 &self.data
127 }
128
129 pub const fn nonce(&self) -> &Group<A> {
131 &self.nonce
132 }
133}
134
135#[cfg(feature = "console")]
136impl<A: Aleo> Eject for Record<A, Plaintext<A>> {
137 type Primitive = console::Record<A::Network, console::Plaintext<A::Network>>;
138
139 fn eject_mode(&self) -> Mode {
141 let owner = match &self.owner {
142 Owner::Public(owner) => match owner.eject_mode() == Mode::Public {
143 true => Mode::Public,
144 false => A::halt("Record::<Plaintext>::eject_mode: 'owner' is not public."),
145 },
146 Owner::Private(plaintext) => match plaintext.eject_mode() == Mode::Private {
147 true => Mode::Private,
148 false => A::halt("Record::<Plaintext>::eject_mode: 'owner' is not private."),
149 },
150 };
151
152 let data = self.data.iter().map(|(_, entry)| entry.eject_mode()).collect::<Vec<_>>().eject_mode();
153 let nonce = self.nonce.eject_mode();
154
155 Mode::combine(owner, [data, nonce])
156 }
157
158 fn eject_value(&self) -> Self::Primitive {
160 let owner = match &self.owner {
161 Owner::Public(owner) => console::Owner::Public(owner.eject_value()),
162 Owner::Private(plaintext) => console::Owner::Private(plaintext.eject_value()),
163 };
164
165 match Self::Primitive::from_plaintext(
166 owner,
167 self.data.iter().map(|(identifier, entry)| (identifier, entry).eject_value()).collect::<IndexMap<_, _>>(),
168 self.nonce.eject_value(),
169 ) {
170 Ok(record) => record,
171 Err(error) => A::halt(format!("Record::<Plaintext>::eject_value: {error}")),
172 }
173 }
174}
175
176#[cfg(feature = "console")]
177impl<A: Aleo> Eject for Record<A, Ciphertext<A>> {
178 type Primitive = console::Record<A::Network, console::Ciphertext<A::Network>>;
179
180 fn eject_mode(&self) -> Mode {
182 let owner = match &self.owner {
183 Owner::Public(owner) => match owner.eject_mode() == Mode::Public {
184 true => Mode::Public,
185 false => A::halt("Record::<Ciphertext>::eject_mode: 'owner' is not public."),
186 },
187 Owner::Private(plaintext) => match plaintext.eject_mode() == Mode::Private {
188 true => Mode::Private,
189 false => A::halt("Record::<Ciphertext>::eject_mode: 'owner' is not private."),
190 },
191 };
192
193 let data = self.data.iter().map(|(_, entry)| entry.eject_mode()).collect::<Vec<_>>().eject_mode();
194 let nonce = self.nonce.eject_mode();
195
196 Mode::combine(owner, [data, nonce])
197 }
198
199 fn eject_value(&self) -> Self::Primitive {
201 let owner = match &self.owner {
202 Owner::Public(owner) => console::Owner::Public(owner.eject_value()),
203 Owner::Private(plaintext) => console::Owner::Private(plaintext.eject_value()),
204 };
205
206 match Self::Primitive::from_ciphertext(
207 owner,
208 self.data.iter().map(|(identifier, entry)| (identifier, entry).eject_value()).collect::<IndexMap<_, _>>(),
209 self.nonce.eject_value(),
210 ) {
211 Ok(record) => record,
212 Err(error) => A::halt(format!("Record::<Ciphertext>::eject_value: {error}")),
213 }
214 }
215}
216
217#[cfg(feature = "console")]
218impl<A: Aleo, Private: Visibility<A>> TypeName for Record<A, Private> {
219 fn type_name() -> &'static str {
220 "record"
221 }
222}