snarkvm_circuit_program/data/record/
mod.rs#[cfg(test)]
use snarkvm_circuit_types::environment::assert_scope;
mod entry;
pub use entry::Entry;
mod helpers;
pub use helpers::Owner;
mod decrypt;
mod encrypt;
mod equal;
mod find;
mod num_randomizers;
mod serial_number;
mod tag;
mod to_bits;
mod to_commitment;
mod to_fields;
use crate::{Access, Ciphertext, Identifier, Plaintext, ProgramID, Visibility};
use snarkvm_circuit_account::{PrivateKey, ViewKey};
use snarkvm_circuit_network::Aleo;
use snarkvm_circuit_types::{Boolean, Field, Group, Scalar, U32, environment::prelude::*};
#[derive(Clone)]
pub struct Record<A: Aleo, Private: Visibility<A>> {
owner: Owner<A, Private>,
data: IndexMap<Identifier<A>, Entry<A, Private>>,
nonce: Group<A>,
}
#[cfg(feature = "console")]
impl<A: Aleo> Inject for Record<A, Plaintext<A>> {
type Primitive = console::Record<A::Network, console::Plaintext<A::Network>>;
fn new(_: Mode, record: Self::Primitive) -> Self {
Self {
owner: Owner::new(Mode::Private, record.owner().clone()),
data: Inject::new(Mode::Private, record.data().clone()),
nonce: Group::new(Mode::Private, *record.nonce()),
}
}
}
#[cfg(feature = "console")]
impl<A: Aleo> Inject for Record<A, Ciphertext<A>> {
type Primitive = console::Record<A::Network, console::Ciphertext<A::Network>>;
fn new(_: Mode, record: Self::Primitive) -> Self {
Self {
owner: Owner::new(Mode::Private, record.owner().clone()),
data: Inject::new(Mode::Private, record.data().clone()),
nonce: Group::new(Mode::Private, *record.nonce()),
}
}
}
#[cfg(feature = "console")]
impl<A: Aleo, Private: Visibility<A>> Record<A, Private> {
pub fn from_plaintext(
owner: Owner<A, Plaintext<A>>,
data: IndexMap<Identifier<A>, Entry<A, Plaintext<A>>>,
nonce: Group<A>,
) -> Result<Record<A, Plaintext<A>>> {
ensure!(!has_duplicates(data.iter().map(|(name, ..)| name)), "A duplicate entry name was found in a record");
ensure!(
data.len() <= <A::Network as console::Network>::MAX_DATA_ENTRIES,
"Found a record that exceeds size ({})",
data.len()
);
Ok(Record { owner, data, nonce })
}
pub fn from_ciphertext(
owner: Owner<A, Ciphertext<A>>,
data: IndexMap<Identifier<A>, Entry<A, Ciphertext<A>>>,
nonce: Group<A>,
) -> Result<Record<A, Ciphertext<A>>> {
ensure!(!has_duplicates(data.iter().map(|(name, ..)| name)), "A duplicate entry name was found in a record");
ensure!(
data.len() <= <A::Network as console::Network>::MAX_DATA_ENTRIES,
"Found a record that exceeds size ({})",
data.len()
);
Ok(Record { owner, data, nonce })
}
}
impl<A: Aleo, Private: Visibility<A>> Record<A, Private> {
pub const fn owner(&self) -> &Owner<A, Private> {
&self.owner
}
pub const fn data(&self) -> &IndexMap<Identifier<A>, Entry<A, Private>> {
&self.data
}
pub const fn nonce(&self) -> &Group<A> {
&self.nonce
}
}
#[cfg(feature = "console")]
impl<A: Aleo> Eject for Record<A, Plaintext<A>> {
type Primitive = console::Record<A::Network, console::Plaintext<A::Network>>;
fn eject_mode(&self) -> Mode {
let owner = match &self.owner {
Owner::Public(owner) => match owner.eject_mode() == Mode::Public {
true => Mode::Public,
false => A::halt("Record::<Plaintext>::eject_mode: 'owner' is not public."),
},
Owner::Private(plaintext) => match plaintext.eject_mode() == Mode::Private {
true => Mode::Private,
false => A::halt("Record::<Plaintext>::eject_mode: 'owner' is not private."),
},
};
let data = self.data.iter().map(|(_, entry)| entry.eject_mode()).collect::<Vec<_>>().eject_mode();
let nonce = self.nonce.eject_mode();
Mode::combine(owner, [data, nonce])
}
fn eject_value(&self) -> Self::Primitive {
let owner = match &self.owner {
Owner::Public(owner) => console::Owner::Public(owner.eject_value()),
Owner::Private(plaintext) => console::Owner::Private(plaintext.eject_value()),
};
match Self::Primitive::from_plaintext(
owner,
self.data.iter().map(|(identifier, entry)| (identifier, entry).eject_value()).collect::<IndexMap<_, _>>(),
self.nonce.eject_value(),
) {
Ok(record) => record,
Err(error) => A::halt(format!("Record::<Plaintext>::eject_value: {error}")),
}
}
}
#[cfg(feature = "console")]
impl<A: Aleo> Eject for Record<A, Ciphertext<A>> {
type Primitive = console::Record<A::Network, console::Ciphertext<A::Network>>;
fn eject_mode(&self) -> Mode {
let owner = match &self.owner {
Owner::Public(owner) => match owner.eject_mode() == Mode::Public {
true => Mode::Public,
false => A::halt("Record::<Ciphertext>::eject_mode: 'owner' is not public."),
},
Owner::Private(plaintext) => match plaintext.eject_mode() == Mode::Private {
true => Mode::Private,
false => A::halt("Record::<Ciphertext>::eject_mode: 'owner' is not private."),
},
};
let data = self.data.iter().map(|(_, entry)| entry.eject_mode()).collect::<Vec<_>>().eject_mode();
let nonce = self.nonce.eject_mode();
Mode::combine(owner, [data, nonce])
}
fn eject_value(&self) -> Self::Primitive {
let owner = match &self.owner {
Owner::Public(owner) => console::Owner::Public(owner.eject_value()),
Owner::Private(plaintext) => console::Owner::Private(plaintext.eject_value()),
};
match Self::Primitive::from_ciphertext(
owner,
self.data.iter().map(|(identifier, entry)| (identifier, entry).eject_value()).collect::<IndexMap<_, _>>(),
self.nonce.eject_value(),
) {
Ok(record) => record,
Err(error) => A::halt(format!("Record::<Ciphertext>::eject_value: {error}")),
}
}
}
#[cfg(feature = "console")]
impl<A: Aleo, Private: Visibility<A>> TypeName for Record<A, Private> {
fn type_name() -> &'static str {
"record"
}
}