use super::*;
impl<A: Aleo> Record<A, Plaintext<A>> {
pub fn encrypt(&self, randomizer: &Scalar<A>) -> Record<A, Ciphertext<A>> {
self.encrypt_symmetric(randomizer).0
}
pub fn encrypt_symmetric(&self, randomizer: &Scalar<A>) -> (Record<A, Ciphertext<A>>, Field<A>) {
A::assert_eq(&self.nonce, A::g_scalar_multiply(randomizer))
.expect("Randomizer must correspond to record nonce");
let record_view_key = ((*self.owner).to_group() * randomizer).to_x_coordinate();
let encrypted_record = self.encrypt_symmetric_unchecked(record_view_key.clone());
(encrypted_record, record_view_key)
}
pub fn encrypt_symmetric_unchecked(&self, record_view_key: Field<A>) -> Record<A, Ciphertext<A>> {
let num_randomizers = self.num_randomizers();
let randomizers = A::hash_many_psd8(&[A::encryption_domain(), record_view_key], num_randomizers);
self.encrypt_with_randomizers(&randomizers)
}
fn encrypt_with_randomizers(&self, randomizers: &[Field<A>]) -> Record<A, Ciphertext<A>> {
let mut index: usize = 0;
let owner = match self.owner.is_public().eject_value() {
true => self.owner.encrypt(&[]),
false => self.owner.encrypt(&[randomizers[index].clone()]),
};
if owner.is_private().eject_value() {
index += 1;
}
let mut encrypted_data = IndexMap::with_capacity(self.data.len());
for (id, entry, num_randomizers) in self.data.iter().map(|(id, entry)| (id, entry, entry.num_randomizers())) {
let randomizers = &randomizers[index..index + num_randomizers as usize];
let entry = match entry {
Entry::Constant(plaintext) => Entry::Constant(plaintext.clone()),
Entry::Public(plaintext) => Entry::Public(plaintext.clone()),
Entry::Private(private) => Entry::Private(private.encrypt_with_randomizers(randomizers)),
};
if encrypted_data.insert(id.clone(), entry).is_some() {
A::halt(format!("Duplicate identifier in record: {id}"))
}
index += num_randomizers as usize;
}
Record { owner, data: encrypted_data, nonce: self.nonce.clone(), version: self.version.clone() }
}
}