/ console / program / src / data / record / helpers / owner.rs
owner.rs
  1  // Copyright (c) 2019-2025 Alpha-Delta Network Inc.
  2  // This file is part of the alphavm library.
  3  
  4  // Licensed under the Apache License, Version 2.0 (the "License");
  5  // you may not use this file except in compliance with the License.
  6  // You may obtain a copy of the License at:
  7  
  8  // http://www.apache.org/licenses/LICENSE-2.0
  9  
 10  // Unless required by applicable law or agreed to in writing, software
 11  // distributed under the License is distributed on an "AS IS" BASIS,
 12  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13  // See the License for the specific language governing permissions and
 14  // limitations under the License.
 15  
 16  use crate::{Ciphertext, Entry, Literal, Plaintext};
 17  use alphavm_console_network::prelude::*;
 18  use alphavm_console_types::{Address, Boolean, Field};
 19  
 20  /// A value stored in program data.
 21  #[derive(Clone)]
 22  pub enum Owner<N: Network, Private: Visibility> {
 23      /// A publicly-visible value.
 24      Public(Address<N>),
 25      /// A private value is encrypted under the account owner's address.
 26      Private(Private),
 27  }
 28  
 29  impl<N: Network> Deref for Owner<N, Plaintext<N>> {
 30      type Target = Address<N>;
 31  
 32      /// Returns the address of the owner.
 33      fn deref(&self) -> &Self::Target {
 34          match self {
 35              Self::Public(public) => public,
 36              Self::Private(Plaintext::Literal(Literal::Address(address), ..)) => address,
 37              _ => N::halt("Internal error: plaintext deref corrupted in record owner"),
 38          }
 39      }
 40  }
 41  
 42  impl<N: Network, Private: Visibility> Owner<N, Private> {
 43      /// Returns `true` if `self` is public.
 44      pub const fn is_public(&self) -> bool {
 45          matches!(self, Self::Public(..))
 46      }
 47  
 48      /// Returns `true` if `self` is private.
 49      pub const fn is_private(&self) -> bool {
 50          matches!(self, Self::Private(..))
 51      }
 52  }
 53  
 54  impl<N: Network> Owner<N, Plaintext<N>> {
 55      /// Returns the owner as an `Entry`.
 56      pub fn to_entry(&self) -> Entry<N, Plaintext<N>> {
 57          match self {
 58              Self::Public(owner) => Entry::Public(Plaintext::from(Literal::Address(*owner))),
 59              Self::Private(plaintext) => Entry::Private(plaintext.clone()),
 60          }
 61      }
 62  }
 63  
 64  impl<N: Network, Private: Visibility<Boolean = Boolean<N>>> Eq for Owner<N, Private> {}
 65  
 66  impl<N: Network, Private: Visibility<Boolean = Boolean<N>>> PartialEq for Owner<N, Private> {
 67      /// Returns `true` if `self` and `other` are equal.
 68      fn eq(&self, other: &Self) -> bool {
 69          *self.is_equal(other)
 70      }
 71  }
 72  
 73  impl<N: Network, Private: Visibility<Boolean = Boolean<N>>> Equal<Self> for Owner<N, Private> {
 74      type Output = Boolean<N>;
 75  
 76      /// Returns `true` if `self` and `other` are equal.
 77      fn is_equal(&self, other: &Self) -> Self::Output {
 78          match (self, other) {
 79              (Self::Public(a), Self::Public(b)) => a.is_equal(b),
 80              (Self::Private(a), Self::Private(b)) => a.is_equal(b),
 81              (Self::Public(_), _) | (Self::Private(_), _) => Boolean::new(false),
 82          }
 83      }
 84  
 85      /// Returns `true` if `self` and `other` are *not* equal.
 86      fn is_not_equal(&self, other: &Self) -> Self::Output {
 87          match (self, other) {
 88              (Self::Public(a), Self::Public(b)) => a.is_not_equal(b),
 89              (Self::Private(a), Self::Private(b)) => a.is_not_equal(b),
 90              (Self::Public(_), _) | (Self::Private(_), _) => Boolean::new(true),
 91          }
 92      }
 93  }
 94  
 95  impl<N: Network> Owner<N, Plaintext<N>> {
 96      /// Encrypts `self` under the given randomizer.
 97      pub fn encrypt_with_randomizer(&self, randomizer: &[Field<N>]) -> Result<Owner<N, Ciphertext<N>>> {
 98          match self {
 99              Self::Public(public) => {
100                  // Ensure there is exactly zero randomizers.
101                  ensure!(randomizer.is_empty(), "Expected 0 randomizers, found {}", randomizer.len());
102                  // Return the owner.
103                  Ok(Owner::Public(*public))
104              }
105              Self::Private(Plaintext::Literal(Literal::Address(address), ..)) => {
106                  // Ensure there is exactly one randomizer.
107                  ensure!(randomizer.len() == 1, "Expected 1 randomizer, found {}", randomizer.len());
108                  // Encrypt the owner.
109                  let ciphertext = address.to_field()? + randomizer[0];
110                  // Return the encrypted owner.
111                  Ok(Owner::Private(Ciphertext::from_fields(&[ciphertext])?))
112              }
113              _ => bail!("Internal error: plaintext encryption corrupted in record owner"),
114          }
115      }
116  }
117  
118  impl<N: Network> Owner<N, Ciphertext<N>> {
119      /// Decrypts the owner under the given randomizer.
120      pub fn decrypt_with_randomizer(&self, randomizer: &[Field<N>]) -> Result<Owner<N, Plaintext<N>>> {
121          match self {
122              Self::Public(public) => {
123                  // Ensure there is exactly zero randomizers.
124                  ensure!(randomizer.is_empty(), "Expected 0 randomizers, found {}", randomizer.len());
125                  // Return the owner.
126                  Ok(Owner::Public(*public))
127              }
128              Self::Private(ciphertext) => {
129                  // Ensure there is exactly one randomizer.
130                  ensure!(randomizer.len() == 1, "Expected 1 randomizer, found {}", randomizer.len());
131                  // Ensure there is exactly one field element in the ciphertext.
132                  ensure!(ciphertext.len() == 1, "Expected 1 ciphertext, found {}", ciphertext.len());
133                  // Decrypt the owner.
134                  let owner = Address::from_field(&(ciphertext[0] - randomizer[0]))?;
135                  // Return the owner.
136                  Ok(Owner::Private(Plaintext::from(Literal::Address(owner))))
137              }
138          }
139      }
140  }
141  
142  impl<N: Network> Debug for Owner<N, Plaintext<N>> {
143      /// Prints the owner as a string.
144      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
145          Display::fmt(self, f)
146      }
147  }
148  
149  impl<N: Network> Display for Owner<N, Plaintext<N>> {
150      /// Prints the owner as a string, i.e. `ax1xxx.public`.
151      fn fmt(&self, f: &mut Formatter) -> fmt::Result {
152          match self {
153              Self::Public(owner) => write!(f, "{owner}.public"),
154              Self::Private(Plaintext::Literal(Literal::Address(owner), ..)) => write!(f, "{owner}.private"),
155              _ => N::halt("Internal error: plaintext fmt corrupted in record owner"),
156          }
157      }
158  }