snarkvm_circuit_program/data/record/helpers/
owner.rsuse crate::{Ciphertext, Entry, Literal, Plaintext, Visibility};
use snarkvm_circuit_network::Aleo;
use snarkvm_circuit_types::{Address, Boolean, Field, environment::prelude::*};
#[derive(Clone)]
pub enum Owner<A: Aleo, Private: Visibility<A>> {
Public(Address<A>),
Private(Private),
}
#[cfg(feature = "console")]
impl<A: Aleo> Inject for Owner<A, Plaintext<A>> {
type Primitive = console::Owner<A::Network, console::Plaintext<A::Network>>;
fn new(_: Mode, owner: Self::Primitive) -> Self {
match owner {
console::Owner::Public(owner) => Self::Public(Address::new(Mode::Private, owner)),
console::Owner::Private(console::Plaintext::Literal(console::Literal::Address(owner), ..)) => {
Self::Private(Plaintext::Literal(
Literal::Address(Address::new(Mode::Private, owner)),
Default::default(),
))
}
_ => A::halt("Owner::<Plaintext>::new: Invalid primitive type for owner"),
}
}
}
#[cfg(feature = "console")]
impl<A: Aleo> Inject for Owner<A, Ciphertext<A>> {
type Primitive = console::Owner<A::Network, console::Ciphertext<A::Network>>;
fn new(_: Mode, owner: Self::Primitive) -> Self {
match owner {
console::Owner::Public(owner) => Self::Public(Address::new(Mode::Private, owner)),
console::Owner::Private(ciphertext) => Self::Private(Ciphertext::new(Mode::Private, ciphertext)),
}
}
}
impl<A: Aleo> Deref for Owner<A, Plaintext<A>> {
type Target = Address<A>;
fn deref(&self) -> &Self::Target {
match self {
Self::Public(public) => public,
Self::Private(Plaintext::Literal(Literal::Address(address), ..)) => address,
_ => A::halt("Internal error: plaintext deref corrupted in record owner"),
}
}
}
impl<A: Aleo, Private: Visibility<A>> Owner<A, Private> {
pub fn is_public(&self) -> Boolean<A> {
Boolean::constant(matches!(self, Self::Public(..)))
}
pub fn is_private(&self) -> Boolean<A> {
Boolean::constant(matches!(self, Self::Private(..)))
}
}
impl<A: Aleo> Owner<A, Plaintext<A>> {
pub fn to_entry(&self) -> Entry<A, Plaintext<A>> {
match self {
Self::Public(owner) => Entry::Public(Plaintext::from(Literal::Address(owner.clone()))),
Self::Private(plaintext, ..) => Entry::Private(plaintext.clone()),
}
}
}
impl<A: Aleo, Private: Visibility<A>> Equal<Self> for Owner<A, Private> {
type Output = Boolean<A>;
fn is_equal(&self, other: &Self) -> Self::Output {
match (self, other) {
(Self::Public(a), Self::Public(b)) => a.is_equal(b),
(Self::Private(a), Self::Private(b)) => a.is_equal(b),
(Self::Public(_), _) | (Self::Private(_), _) => Boolean::constant(false),
}
}
fn is_not_equal(&self, other: &Self) -> Self::Output {
match (self, other) {
(Self::Public(a), Self::Public(b)) => a.is_not_equal(b),
(Self::Private(a), Self::Private(b)) => a.is_not_equal(b),
(Self::Public(_), _) | (Self::Private(_), _) => Boolean::constant(true),
}
}
}
impl<A: Aleo> Owner<A, Plaintext<A>> {
pub fn encrypt(&self, randomizer: &[Field<A>]) -> Owner<A, Ciphertext<A>> {
match self {
Self::Public(public) => {
if !randomizer.is_empty() {
A::halt(format!("Expected 0 randomizers, found {}", randomizer.len()))
}
Owner::Public(public.clone())
}
Self::Private(Plaintext::Literal(Literal::Address(address), ..)) => {
if randomizer.len() != 1 {
A::halt(format!("Expected 1 randomizer, found {}", randomizer.len()))
}
let ciphertext = address.to_field() + &randomizer[0];
Owner::Private(Ciphertext::from_fields(&[ciphertext]))
}
_ => A::halt("Internal error: plaintext encryption corrupted in record owner"),
}
}
}
impl<A: Aleo> Owner<A, Ciphertext<A>> {
pub fn decrypt(&self, randomizer: &[Field<A>]) -> Owner<A, Plaintext<A>> {
match self {
Self::Public(public) => {
if !randomizer.is_empty() {
A::halt(format!("Expected 0 randomizers, found {}", randomizer.len()))
}
Owner::Public(public.clone())
}
Self::Private(ciphertext) => {
if randomizer.len() != 1 {
A::halt(format!("Expected 1 randomizer, found {}", randomizer.len()))
}
if ciphertext.len() != 1 {
A::halt(format!("Expected 1 ciphertext, found {}", ciphertext.len()))
}
let owner = Address::from_field(&ciphertext[0] - &randomizer[0]);
Owner::Private(Plaintext::from(Literal::Address(owner)))
}
}
}
}
impl<A: Aleo> ToBits for Owner<A, Plaintext<A>> {
type Boolean = Boolean<A>;
fn write_bits_le(&self, vec: &mut Vec<Boolean<A>>) {
vec.push(self.is_private());
match self {
Self::Public(public) => public.write_bits_le(vec),
Self::Private(Plaintext::Literal(Literal::Address(address), ..)) => address.write_bits_le(vec),
_ => A::halt("Internal error: plaintext to_bits_le corrupted in record owner"),
};
}
fn write_bits_be(&self, vec: &mut Vec<Boolean<A>>) {
vec.push(self.is_private());
match self {
Self::Public(public) => public.write_bits_be(vec),
Self::Private(Plaintext::Literal(Literal::Address(address), ..)) => address.write_bits_be(vec),
_ => A::halt("Internal error: plaintext to_bits_be corrupted in record owner"),
};
}
}
impl<A: Aleo> ToBits for Owner<A, Ciphertext<A>> {
type Boolean = Boolean<A>;
fn write_bits_le(&self, vec: &mut Vec<Boolean<A>>) {
vec.push(self.is_private());
match self {
Self::Public(public) => public.write_bits_le(vec),
Self::Private(ciphertext) => {
match ciphertext.len() == 1 {
true => ciphertext[0].write_bits_le(vec),
false => A::halt("Internal error: ciphertext to_bits_le corrupted in record owner"),
}
}
};
}
fn write_bits_be(&self, vec: &mut Vec<Boolean<A>>) {
vec.push(self.is_private());
match self {
Self::Public(public) => public.write_bits_be(vec),
Self::Private(ciphertext) => {
match ciphertext.len() == 1 {
true => ciphertext[0].write_bits_be(vec),
false => A::halt("Internal error: ciphertext to_bits_be corrupted in record owner"),
}
}
};
}
}