use crate::{
atomic_batch_scope,
cow_to_cloned,
cow_to_copied,
helpers::{Map, MapRead},
};
use console::{
network::prelude::*,
program::{Identifier, Plaintext, ProgramID, Value},
types::Field,
};
use synthesizer_program::{FinalizeOperation, FinalizeStoreTrait};
use anyhow::Result;
use core::marker::PhantomData;
use indexmap::{IndexMap, IndexSet};
pub trait FinalizeStorage<N: Network>: 'static + Clone + Send + Sync {
type ProgramIDMap: for<'a> Map<'a, ProgramID<N>, IndexSet<Identifier<N>>>;
type MappingIDMap: for<'a> Map<'a, (ProgramID<N>, Identifier<N>), Field<N>>;
type KeyValueIDMap: for<'a> Map<'a, Field<N>, IndexMap<Field<N>, Field<N>>>;
type KeyMap: for<'a> Map<'a, Field<N>, Plaintext<N>>;
type ValueMap: for<'a> Map<'a, Field<N>, Value<N>>;
fn open(dev: Option<u16>) -> Result<Self>;
fn program_id_map(&self) -> &Self::ProgramIDMap;
fn mapping_id_map(&self) -> &Self::MappingIDMap;
fn key_value_id_map(&self) -> &Self::KeyValueIDMap;
fn key_map(&self) -> &Self::KeyMap;
fn value_map(&self) -> &Self::ValueMap;
fn dev(&self) -> Option<u16>;
fn start_atomic(&self) {
self.program_id_map().start_atomic();
self.mapping_id_map().start_atomic();
self.key_value_id_map().start_atomic();
self.key_map().start_atomic();
self.value_map().start_atomic();
}
fn is_atomic_in_progress(&self) -> bool {
self.program_id_map().is_atomic_in_progress()
|| self.mapping_id_map().is_atomic_in_progress()
|| self.key_value_id_map().is_atomic_in_progress()
|| self.key_map().is_atomic_in_progress()
|| self.value_map().is_atomic_in_progress()
}
fn atomic_checkpoint(&self) {
self.program_id_map().atomic_checkpoint();
self.mapping_id_map().atomic_checkpoint();
self.key_value_id_map().atomic_checkpoint();
self.key_map().atomic_checkpoint();
self.value_map().atomic_checkpoint();
}
fn clear_latest_checkpoint(&self) {
self.program_id_map().clear_latest_checkpoint();
self.mapping_id_map().clear_latest_checkpoint();
self.key_value_id_map().clear_latest_checkpoint();
self.key_map().clear_latest_checkpoint();
self.value_map().clear_latest_checkpoint();
}
fn atomic_rewind(&self) {
self.program_id_map().atomic_rewind();
self.mapping_id_map().atomic_rewind();
self.key_value_id_map().atomic_rewind();
self.key_map().atomic_rewind();
self.value_map().atomic_rewind();
}
fn abort_atomic(&self) {
self.program_id_map().abort_atomic();
self.mapping_id_map().abort_atomic();
self.key_value_id_map().abort_atomic();
self.key_map().abort_atomic();
self.value_map().abort_atomic();
}
fn finish_atomic(&self) -> Result<()> {
self.program_id_map().finish_atomic()?;
self.mapping_id_map().finish_atomic()?;
self.key_value_id_map().finish_atomic()?;
self.key_map().finish_atomic()?;
self.value_map().finish_atomic()
}
fn initialize_mapping(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
) -> Result<FinalizeOperation<N>> {
if self.mapping_id_map().contains_key_speculative(&(*program_id, *mapping_name))? {
bail!("Illegal operation: mapping '{mapping_name}' already exists in storage - cannot initialize again.")
}
let mapping_id = N::hash_bhp1024(&(program_id, mapping_name).to_bits_le())?;
if self.key_value_id_map().contains_key_speculative(&mapping_id)? {
bail!("Illegal operation: mapping ID '{mapping_id}' already exists in storage - cannot initialize again.")
}
let mut mapping_names = match self.program_id_map().get_speculative(program_id)? {
Some(mapping_names) => cow_to_cloned!(mapping_names),
None => IndexSet::new(),
};
if mapping_names.contains(mapping_name) {
bail!("Illegal operation: mapping name '{mapping_name}' already exists in storage - cannot re-initialize.")
}
mapping_names.insert(*mapping_name);
atomic_batch_scope!(self, {
self.program_id_map().insert(*program_id, mapping_names)?;
self.mapping_id_map().insert((*program_id, *mapping_name), mapping_id)?;
self.key_value_id_map().insert(mapping_id, IndexMap::new())?;
Ok(())
})?;
Ok(FinalizeOperation::InitializeMapping(mapping_id))
}
fn insert_key_value(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: Plaintext<N>,
value: Value<N>,
) -> Result<FinalizeOperation<N>> {
let mapping_id = match self.get_mapping_id_speculative(program_id, mapping_name)? {
Some(mapping_id) => mapping_id,
None => bail!("Illegal operation: mapping '{mapping_name}' is not initialized - cannot insert key-value."),
};
let key_id = N::hash_bhp1024(&(mapping_id, N::hash_bhp1024(&key.to_bits_le())?).to_bits_le())?;
let value_id = N::hash_bhp1024(&(key_id, N::hash_bhp1024(&value.to_bits_le())?).to_bits_le())?;
if self.key_map().contains_key_speculative(&key_id)? {
bail!("Illegal operation: key ID '{key_id}' already exists in storage - cannot insert again.")
}
let mut key_value_ids = match self.key_value_id_map().get_speculative(&mapping_id)? {
Some(key_value_ids) => cow_to_cloned!(key_value_ids),
None => bail!("Illegal operation: mapping ID '{mapping_id}' is not initialized - cannot insert key-value."),
};
if key_value_ids.contains_key(&key_id) {
bail!("Illegal operation: key ID '{key_id}' already exists in storage - cannot insert key-value.");
}
key_value_ids.insert(key_id, value_id);
atomic_batch_scope!(self, {
self.key_value_id_map().insert(mapping_id, key_value_ids)?;
self.key_map().insert(key_id, key)?;
self.value_map().insert(key_id, value)?;
Ok(())
})?;
Ok(FinalizeOperation::InsertKeyValue(mapping_id, key_id, value_id))
}
fn update_key_value(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: Plaintext<N>,
value: Value<N>,
) -> Result<FinalizeOperation<N>> {
let mapping_id = match self.get_mapping_id_speculative(program_id, mapping_name)? {
Some(mapping_id) => mapping_id,
None => bail!("Illegal operation: mapping '{mapping_name}' is not initialized - cannot update key-value."),
};
let key_id = N::hash_bhp1024(&(mapping_id, N::hash_bhp1024(&key.to_bits_le())?).to_bits_le())?;
let value_id = N::hash_bhp1024(&(key_id, N::hash_bhp1024(&value.to_bits_le())?).to_bits_le())?;
let mut key_value_ids = match self.key_value_id_map().get_speculative(&mapping_id)? {
Some(key_value_ids) => cow_to_cloned!(key_value_ids),
None => {
bail!("Illegal operation: mapping ID '{mapping_id}' is not initialized - cannot update key-value.")
}
};
if !self.key_map().contains_key_speculative(&key_id)? {
if key_value_ids.contains_key(&key_id) {
bail!("Illegal operation: key ID '{key_id}' already exists in storage - cannot update key-value.");
}
}
key_value_ids.insert(key_id, value_id);
let index = match key_value_ids.get_index_of(&key_id) {
Some(index) => u64::try_from(index)?,
None => bail!("Illegal operation: key ID '{key_id}' does not exist in storage - cannot finalize."),
};
atomic_batch_scope!(self, {
self.key_value_id_map().insert(mapping_id, key_value_ids)?;
self.key_map().insert(key_id, key)?;
self.value_map().insert(key_id, value)?;
Ok(())
})?;
Ok(FinalizeOperation::UpdateKeyValue(mapping_id, index, key_id, value_id))
}
fn remove_key_value(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: &Plaintext<N>,
) -> Result<FinalizeOperation<N>> {
let mapping_id = match self.get_mapping_id_speculative(program_id, mapping_name)? {
Some(mapping_id) => mapping_id,
None => bail!("Illegal operation: mapping '{mapping_name}' is not initialized - cannot remove key-value."),
};
let key_id = N::hash_bhp1024(&(mapping_id, N::hash_bhp1024(&key.to_bits_le())?).to_bits_le())?;
let mut key_value_ids = match self.key_value_id_map().get_speculative(&mapping_id)? {
Some(key_value_ids) => cow_to_cloned!(key_value_ids),
None => bail!("Illegal operation: mapping ID '{mapping_id}' is not initialized - cannot remove key-value."),
};
if !key_value_ids.contains_key(&key_id) {
bail!("Illegal operation: key ID '{key_id}' does not exist in storage - cannot remove key-value.");
}
let index = match key_value_ids.get_index_of(&key_id) {
Some(index) => u64::try_from(index)?,
None => bail!("Illegal operation: key ID '{key_id}' does not exist in storage - cannot finalize."),
};
key_value_ids.remove(&key_id);
atomic_batch_scope!(self, {
self.key_value_id_map().insert(mapping_id, key_value_ids)?;
self.key_map().remove(&key_id)?;
self.value_map().remove(&key_id)?;
Ok(())
})?;
Ok(FinalizeOperation::RemoveKeyValue(mapping_id, index))
}
fn remove_mapping(&self, program_id: &ProgramID<N>, mapping_name: &Identifier<N>) -> Result<FinalizeOperation<N>> {
let mapping_id = match self.get_mapping_id_speculative(program_id, mapping_name)? {
Some(mapping_id) => mapping_id,
None => bail!("Illegal operation: mapping '{mapping_name}' is not initialized - cannot remove mapping."),
};
let key_value_ids = match self.key_value_id_map().get_speculative(&mapping_id)? {
Some(key_value_ids) => key_value_ids,
None => bail!("Illegal operation: mapping ID '{mapping_id}' is not initialized - cannot remove mapping."),
};
let mut mapping_names = match self.program_id_map().get_speculative(program_id)? {
Some(mapping_names) => cow_to_cloned!(mapping_names),
None => bail!("Illegal operation: program ID '{program_id}' is not initialized - cannot remove mapping."),
};
if !mapping_names.contains(mapping_name) {
bail!("Illegal operation: mapping '{mapping_name}' does not exist in storage - cannot remove mapping.");
}
mapping_names.remove(mapping_name);
atomic_batch_scope!(self, {
self.program_id_map().insert(*program_id, mapping_names)?;
self.mapping_id_map().remove(&(*program_id, *mapping_name))?;
self.key_value_id_map().remove(&mapping_id)?;
for key_id in key_value_ids.keys() {
self.key_map().remove(key_id)?;
self.value_map().remove(key_id)?;
}
Ok(())
})?;
Ok(FinalizeOperation::RemoveMapping(mapping_id))
}
fn remove_program(&self, program_id: &ProgramID<N>) -> Result<()> {
let mapping_names = match self.program_id_map().get_speculative(program_id)? {
Some(mapping_names) => mapping_names,
None => bail!("Illegal operation: program ID '{program_id}' is not initialized - cannot remove mapping."),
};
atomic_batch_scope!(self, {
self.program_id_map().remove(program_id)?;
for mapping_name in mapping_names.iter() {
let mapping_id = match self.get_mapping_id_speculative(program_id, mapping_name)? {
Some(mapping_id) => mapping_id,
None => {
bail!("Illegal operation: mapping '{mapping_name}' is not initialized - cannot remove mapping.")
}
};
let key_value_ids = match self.key_value_id_map().get_speculative(&mapping_id)? {
Some(key_value_ids) => key_value_ids,
None => {
bail!(
"Illegal operation: mapping ID '{mapping_id}' is not initialized - cannot remove mapping."
)
}
};
self.mapping_id_map().remove(&(*program_id, *mapping_name))?;
self.key_value_id_map().remove(&mapping_id)?;
for key_id in key_value_ids.keys() {
self.key_map().remove(key_id)?;
self.value_map().remove(key_id)?;
}
}
Ok(())
})
}
fn contains_program_confirmed(&self, program_id: &ProgramID<N>) -> Result<bool> {
self.program_id_map().contains_key_confirmed(program_id)
}
fn contains_mapping_confirmed(&self, program_id: &ProgramID<N>, mapping_name: &Identifier<N>) -> Result<bool> {
self.mapping_id_map().contains_key_confirmed(&(*program_id, *mapping_name))
}
fn contains_key_confirmed(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: &Plaintext<N>,
) -> Result<bool> {
let mapping_id = match self.get_mapping_id_speculative(program_id, mapping_name)? {
Some(mapping_id) => mapping_id,
None => return Ok(false),
};
let key_id = N::hash_bhp1024(&(mapping_id, N::hash_bhp1024(&key.to_bits_le())?).to_bits_le())?;
self.key_map().contains_key_confirmed(&key_id)
}
fn contains_key_speculative(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: &Plaintext<N>,
) -> Result<bool> {
let mapping_id = match self.get_mapping_id_speculative(program_id, mapping_name)? {
Some(mapping_id) => mapping_id,
None => return Ok(false),
};
let key_id = N::hash_bhp1024(&(mapping_id, N::hash_bhp1024(&key.to_bits_le())?).to_bits_le())?;
self.key_map().contains_key_speculative(&key_id)
}
fn get_mapping_names_confirmed(&self, program_id: &ProgramID<N>) -> Result<Option<IndexSet<Identifier<N>>>> {
match self.program_id_map().get_confirmed(program_id)? {
Some(names) => Ok(Some(cow_to_cloned!(names))),
None => Ok(None),
}
}
fn get_mapping_names_speculative(&self, program_id: &ProgramID<N>) -> Result<Option<IndexSet<Identifier<N>>>> {
match self.program_id_map().get_speculative(program_id)? {
Some(names) => Ok(Some(cow_to_cloned!(names))),
None => Ok(None),
}
}
fn get_mapping_id_confirmed(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
) -> Result<Option<Field<N>>> {
match self.mapping_id_map().get_confirmed(&(*program_id, *mapping_name))? {
Some(mapping_id) => Ok(Some(cow_to_copied!(mapping_id))),
None => Ok(None),
}
}
fn get_mapping_id_speculative(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
) -> Result<Option<Field<N>>> {
match self.mapping_id_map().get_speculative(&(*program_id, *mapping_name))? {
Some(mapping_id) => Ok(Some(cow_to_copied!(mapping_id))),
None => Ok(None),
}
}
fn get_key_id_confirmed(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: &Plaintext<N>,
) -> Result<Option<Field<N>>> {
let mapping_id = match self.get_mapping_id_confirmed(program_id, mapping_name)? {
Some(mapping_id) => mapping_id,
None => return Ok(None),
};
let key_id = N::hash_bhp1024(&(mapping_id, N::hash_bhp1024(&key.to_bits_le())?).to_bits_le())?;
match self.key_map().contains_key_confirmed(&key_id)? {
true => Ok(Some(key_id)),
false => Ok(None),
}
}
fn get_key_id_speculative(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: &Plaintext<N>,
) -> Result<Option<Field<N>>> {
let mapping_id = match self.get_mapping_id_speculative(program_id, mapping_name)? {
Some(mapping_id) => mapping_id,
None => return Ok(None),
};
let key_id = N::hash_bhp1024(&(mapping_id, N::hash_bhp1024(&key.to_bits_le())?).to_bits_le())?;
match self.key_map().contains_key_speculative(&key_id)? {
true => Ok(Some(key_id)),
false => Ok(None),
}
}
fn get_key_speculative(&self, key_id: &Field<N>) -> Result<Option<Plaintext<N>>> {
match self.key_map().get_speculative(key_id)? {
Some(key) => Ok(Some(cow_to_cloned!(key))),
None => Ok(None),
}
}
fn get_value_confirmed(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: &Plaintext<N>,
) -> Result<Option<Value<N>>> {
match self.get_key_id_confirmed(program_id, mapping_name, key)? {
Some(key_id) => self.get_value_from_key_id_confirmed(&key_id),
None => Ok(None),
}
}
fn get_value_speculative(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: &Plaintext<N>,
) -> Result<Option<Value<N>>> {
match self.get_key_id_speculative(program_id, mapping_name, key)? {
Some(key_id) => self.get_value_from_key_id_speculative(&key_id),
None => Ok(None),
}
}
fn get_value_from_key_id_confirmed(&self, key_id: &Field<N>) -> Result<Option<Value<N>>> {
match self.value_map().get_confirmed(key_id)? {
Some(value) => Ok(Some(cow_to_cloned!(value))),
None => Ok(None),
}
}
fn get_value_from_key_id_speculative(&self, key_id: &Field<N>) -> Result<Option<Value<N>>> {
match self.value_map().get_speculative(key_id)? {
Some(value) => Ok(Some(cow_to_cloned!(value))),
None => Ok(None),
}
}
}
#[derive(Clone)]
pub struct FinalizeStore<N: Network, P: FinalizeStorage<N>> {
storage: P,
_phantom: PhantomData<N>,
}
impl<N: Network, P: FinalizeStorage<N>> FinalizeStore<N, P> {
pub fn open(dev: Option<u16>) -> Result<Self> {
Self::from(P::open(dev)?)
}
pub fn from(storage: P) -> Result<Self> {
Ok(Self { storage, _phantom: PhantomData })
}
pub fn start_atomic(&self) {
self.storage.start_atomic();
}
pub fn is_atomic_in_progress(&self) -> bool {
self.storage.is_atomic_in_progress()
}
pub fn atomic_checkpoint(&self) {
self.storage.atomic_checkpoint();
}
pub fn clear_latest_checkpoint(&self) {
self.storage.clear_latest_checkpoint();
}
pub fn atomic_rewind(&self) {
self.storage.atomic_rewind();
}
pub fn abort_atomic(&self) {
self.storage.abort_atomic();
}
pub fn finish_atomic(&self) -> Result<()> {
self.storage.finish_atomic()
}
pub fn dev(&self) -> Option<u16> {
self.storage.dev()
}
}
impl<N: Network, P: FinalizeStorage<N>> FinalizeStoreTrait<N> for FinalizeStore<N, P> {
fn contains_mapping_confirmed(&self, program_id: &ProgramID<N>, mapping_name: &Identifier<N>) -> Result<bool> {
self.storage.contains_mapping_confirmed(program_id, mapping_name)
}
fn contains_key_speculative(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: &Plaintext<N>,
) -> Result<bool> {
self.storage.contains_key_speculative(program_id, mapping_name, key)
}
fn get_value_speculative(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: &Plaintext<N>,
) -> Result<Option<Value<N>>> {
self.storage.get_value_speculative(program_id, mapping_name, key)
}
fn insert_key_value(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: Plaintext<N>,
value: Value<N>,
) -> Result<FinalizeOperation<N>> {
self.storage.insert_key_value(program_id, mapping_name, key, value)
}
fn update_key_value(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: Plaintext<N>,
value: Value<N>,
) -> Result<FinalizeOperation<N>> {
self.storage.update_key_value(program_id, mapping_name, key, value)
}
fn remove_key_value(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: &Plaintext<N>,
) -> Result<FinalizeOperation<N>> {
self.storage.remove_key_value(program_id, mapping_name, key)
}
}
impl<N: Network, P: FinalizeStorage<N>> FinalizeStore<N, P> {
pub fn initialize_mapping(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
) -> Result<FinalizeOperation<N>> {
self.storage.initialize_mapping(program_id, mapping_name)
}
pub fn remove_mapping(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
) -> Result<FinalizeOperation<N>> {
self.storage.remove_mapping(program_id, mapping_name)
}
pub fn remove_program(&self, program_id: &ProgramID<N>) -> Result<()> {
self.storage.remove_program(program_id)
}
}
impl<N: Network, P: FinalizeStorage<N>> FinalizeStore<N, P> {
pub fn contains_program_confirmed(&self, program_id: &ProgramID<N>) -> Result<bool> {
self.storage.contains_program_confirmed(program_id)
}
pub fn contains_key_confirmed(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: &Plaintext<N>,
) -> Result<bool> {
self.storage.contains_key_confirmed(program_id, mapping_name, key)
}
}
impl<N: Network, P: FinalizeStorage<N>> FinalizeStore<N, P> {
pub fn get_mapping_names_confirmed(&self, program_id: &ProgramID<N>) -> Result<Option<IndexSet<Identifier<N>>>> {
self.storage.get_mapping_names_confirmed(program_id)
}
#[deprecated]
pub fn get_mapping_names_speculative(&self, program_id: &ProgramID<N>) -> Result<Option<IndexSet<Identifier<N>>>> {
self.storage.get_mapping_names_speculative(program_id)
}
pub fn get_value_confirmed(
&self,
program_id: &ProgramID<N>,
mapping_name: &Identifier<N>,
key: &Plaintext<N>,
) -> Result<Option<Value<N>>> {
self.storage.get_value_confirmed(program_id, mapping_name, key)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::helpers::memory::FinalizeMemory;
use console::network::Testnet3;
type CurrentNetwork = Testnet3;
fn check_initialize_insert_remove<N: Network>(
finalize_store: &FinalizeStore<N, FinalizeMemory<N>>,
program_id: ProgramID<N>,
mapping_name: Identifier<N>,
) {
let key = Plaintext::from_str("123456789field").unwrap();
let value = Value::from_str("987654321u128").unwrap();
assert!(!finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(finalize_store.remove_mapping(&program_id, &mapping_name).is_err());
finalize_store.initialize_mapping(&program_id, &mapping_name).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
finalize_store.insert_key_value(&program_id, &mapping_name, key.clone(), value.clone()).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert_eq!(value, finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().unwrap());
finalize_store.remove_key_value(&program_id, &mapping_name, &key).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
finalize_store.remove_mapping(&program_id, &mapping_name).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
finalize_store.remove_program(&program_id).unwrap();
assert!(!finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
}
fn check_initialize_update_remove<N: Network>(
finalize_store: &FinalizeStore<N, FinalizeMemory<N>>,
program_id: ProgramID<N>,
mapping_name: Identifier<N>,
) {
let key = Plaintext::from_str("123456789field").unwrap();
let value = Value::from_str("987654321u128").unwrap();
assert!(!finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(finalize_store.remove_mapping(&program_id, &mapping_name).is_err());
finalize_store.initialize_mapping(&program_id, &mapping_name).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
finalize_store.update_key_value(&program_id, &mapping_name, key.clone(), value.clone()).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert_eq!(value, finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().unwrap());
assert!(finalize_store.insert_key_value(&program_id, &mapping_name, key.clone(), value.clone()).is_err());
assert!(finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert_eq!(value, finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().unwrap());
finalize_store.update_key_value(&program_id, &mapping_name, key.clone(), value.clone()).unwrap();
assert!(finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert_eq!(value, finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().unwrap());
{
let new_value = Value::from_str("123456789u128").unwrap();
assert!(
finalize_store.insert_key_value(&program_id, &mapping_name, key.clone(), new_value.clone()).is_err()
);
assert!(finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert_eq!(value, finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().unwrap());
finalize_store.update_key_value(&program_id, &mapping_name, key.clone(), new_value.clone()).unwrap();
assert!(finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert_eq!(
new_value,
finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().unwrap()
);
finalize_store.update_key_value(&program_id, &mapping_name, key.clone(), value.clone()).unwrap();
assert!(finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert_eq!(value, finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().unwrap());
}
finalize_store.remove_key_value(&program_id, &mapping_name, &key).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
finalize_store.remove_mapping(&program_id, &mapping_name).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
finalize_store.remove_program(&program_id).unwrap();
assert!(!finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
}
#[test]
fn test_initialize_insert_remove() {
let program_id = ProgramID::<CurrentNetwork>::from_str("hello.aleo").unwrap();
let mapping_name = Identifier::from_str("account").unwrap();
let program_memory = FinalizeMemory::open(None).unwrap();
let finalize_store = FinalizeStore::from(program_memory).unwrap();
check_initialize_insert_remove(&finalize_store, program_id, mapping_name);
}
#[test]
fn test_initialize_update_remove() {
let program_id = ProgramID::<CurrentNetwork>::from_str("hello.aleo").unwrap();
let mapping_name = Identifier::from_str("account").unwrap();
let program_memory = FinalizeMemory::open(None).unwrap();
let finalize_store = FinalizeStore::from(program_memory).unwrap();
check_initialize_update_remove(&finalize_store, program_id, mapping_name);
}
#[test]
fn test_remove_key_value() {
let program_id = ProgramID::<CurrentNetwork>::from_str("hello.aleo").unwrap();
let mapping_name = Identifier::from_str("account").unwrap();
let program_memory = FinalizeMemory::open(None).unwrap();
let finalize_store = FinalizeStore::from(program_memory).unwrap();
assert!(!finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(finalize_store.remove_mapping(&program_id, &mapping_name).is_err());
finalize_store.initialize_mapping(&program_id, &mapping_name).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
for item in 0..1000 {
let key = Plaintext::from_str(&format!("{item}field")).unwrap();
let value = Value::from_str(&format!("{item}u64")).unwrap();
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
finalize_store.insert_key_value(&program_id, &mapping_name, key.clone(), value.clone()).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert_eq!(value, finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().unwrap());
}
for item in 0..1000 {
let key = Plaintext::from_str(&format!("{item}field")).unwrap();
let value = Value::from_str(&format!("{item}u64")).unwrap();
assert!(finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert_eq!(value, finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().unwrap());
finalize_store.remove_key_value(&program_id, &mapping_name, &key).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
}
}
#[test]
fn test_remove_mapping() {
let program_id = ProgramID::<CurrentNetwork>::from_str("hello.aleo").unwrap();
let mapping_name = Identifier::from_str("account").unwrap();
let program_memory = FinalizeMemory::open(None).unwrap();
let finalize_store = FinalizeStore::from(program_memory).unwrap();
assert!(!finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(finalize_store.remove_mapping(&program_id, &mapping_name).is_err());
finalize_store.initialize_mapping(&program_id, &mapping_name).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
for item in 0..1000 {
let key = Plaintext::from_str(&format!("{item}field")).unwrap();
let value = Value::from_str(&format!("{item}u64")).unwrap();
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
finalize_store.insert_key_value(&program_id, &mapping_name, key.clone(), value.clone()).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert_eq!(value, finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().unwrap());
}
finalize_store.remove_mapping(&program_id, &mapping_name).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
for item in 0..1000 {
let key = Plaintext::from_str(&format!("{item}field")).unwrap();
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
}
}
#[test]
fn test_remove_program() {
let program_id = ProgramID::<CurrentNetwork>::from_str("hello.aleo").unwrap();
let mapping_name = Identifier::from_str("account").unwrap();
let program_memory = FinalizeMemory::open(None).unwrap();
let finalize_store = FinalizeStore::from(program_memory).unwrap();
assert!(!finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(finalize_store.remove_mapping(&program_id, &mapping_name).is_err());
finalize_store.initialize_mapping(&program_id, &mapping_name).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
for item in 0..1000 {
let key = Plaintext::from_str(&format!("{item}field")).unwrap();
let value = Value::from_str(&format!("{item}u64")).unwrap();
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
finalize_store.insert_key_value(&program_id, &mapping_name, key.clone(), value.clone()).unwrap();
assert!(finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert_eq!(value, finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().unwrap());
}
finalize_store.remove_program(&program_id).unwrap();
assert!(!finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
for item in 0..1000 {
let key = Plaintext::from_str(&format!("{item}field")).unwrap();
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
}
}
#[test]
fn test_must_initialize_first() {
let program_id = ProgramID::<CurrentNetwork>::from_str("hello.aleo").unwrap();
let mapping_name = Identifier::from_str("account").unwrap();
let program_memory = FinalizeMemory::open(None).unwrap();
let finalize_store = FinalizeStore::from(program_memory).unwrap();
assert!(!finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(finalize_store.remove_mapping(&program_id, &mapping_name).is_err());
{
let key = Plaintext::from_str("123456789field").unwrap();
let value = Value::from_str("987654321u128").unwrap();
assert!(finalize_store.insert_key_value(&program_id, &mapping_name, key.clone(), value).is_err());
assert!(!finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
assert!(finalize_store.remove_key_value(&program_id, &mapping_name, &key).is_err());
assert!(finalize_store.remove_mapping(&program_id, &mapping_name).is_err());
}
{
let key = Plaintext::from_str("987654321field").unwrap();
let value = Value::from_str("123456789u128").unwrap();
assert!(finalize_store.update_key_value(&program_id, &mapping_name, key.clone(), value).is_err());
assert!(!finalize_store.contains_program_confirmed(&program_id).unwrap());
assert!(!finalize_store.contains_mapping_confirmed(&program_id, &mapping_name).unwrap());
assert!(!finalize_store.contains_key_confirmed(&program_id, &mapping_name, &key).unwrap());
assert!(finalize_store.get_value_speculative(&program_id, &mapping_name, &key).unwrap().is_none());
assert!(finalize_store.remove_key_value(&program_id, &mapping_name, &key).is_err());
assert!(finalize_store.remove_mapping(&program_id, &mapping_name).is_err());
}
check_initialize_insert_remove(&finalize_store, program_id, mapping_name);
check_initialize_update_remove(&finalize_store, program_id, mapping_name);
}
}