use alloc::vec::Vec;
use crate::errors::NoteError;
use crate::utils::serde::{
ByteReader,
ByteWriter,
Deserializable,
DeserializationError,
Serializable,
};
use crate::{Felt, Hasher, MAX_NOTE_STORAGE_ITEMS, Word};
#[derive(Clone, Debug)]
pub struct NoteStorage {
items: Vec<Felt>,
commitment: Word,
}
impl NoteStorage {
pub fn new(items: Vec<Felt>) -> Result<Self, NoteError> {
if items.len() > MAX_NOTE_STORAGE_ITEMS {
return Err(NoteError::TooManyStorageItems(items.len()));
}
let commitment = Hasher::hash_elements(&items);
Ok(Self { items, commitment })
}
pub fn commitment(&self) -> Word {
self.commitment
}
pub fn num_items(&self) -> u16 {
const _: () = assert!(MAX_NOTE_STORAGE_ITEMS <= u16::MAX as usize);
debug_assert!(
self.items.len() <= MAX_NOTE_STORAGE_ITEMS,
"The constructor should have checked the number of storage items"
);
self.items.len() as u16
}
pub fn is_empty(&self) -> bool {
self.items.is_empty()
}
pub fn items(&self) -> &[Felt] {
&self.items
}
pub fn to_elements(&self) -> Vec<Felt> {
self.items.to_vec()
}
}
impl Default for NoteStorage {
fn default() -> Self {
Self::new(vec![]).expect("empty storage should be valid")
}
}
impl PartialEq for NoteStorage {
fn eq(&self, other: &Self) -> bool {
let NoteStorage { items, commitment: _ } = self;
items == &other.items
}
}
impl Eq for NoteStorage {}
impl From<NoteStorage> for Vec<Felt> {
fn from(value: NoteStorage) -> Self {
value.items
}
}
impl TryFrom<Vec<Felt>> for NoteStorage {
type Error = NoteError;
fn try_from(value: Vec<Felt>) -> Result<Self, Self::Error> {
NoteStorage::new(value)
}
}
impl Serializable for NoteStorage {
fn write_into<W: ByteWriter>(&self, target: &mut W) {
let NoteStorage { items, commitment: _commitment } = self;
target.write_u16(items.len().try_into().expect("storage items len is not a u16 value"));
target.write_many(items);
}
fn get_size_hint(&self) -> usize {
2 + self.items.len() * 8
}
}
impl Deserializable for NoteStorage {
fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
let len = source.read_u16()? as usize;
let items = source.read_many_iter(len)?.collect::<Result<Vec<Felt>, _>>()?;
Self::new(items).map_err(|v| DeserializationError::InvalidValue(format!("{v}")))
}
}
#[cfg(test)]
mod tests {
use miden_crypto::utils::Deserializable;
use super::{Felt, NoteStorage, Serializable};
#[test]
fn test_storage_item_ordering() {
let storage_items = vec![Felt::new(1), Felt::new(2), Felt::new(3)];
let expected_ordering = vec![Felt::new(1), Felt::new(2), Felt::new(3)];
let note_storage = NoteStorage::new(storage_items).expect("note created should succeed");
assert_eq!(&expected_ordering, note_storage.items());
}
#[test]
fn test_storage_serialization() {
let storage_items = vec![Felt::new(1), Felt::new(2), Felt::new(3)];
let note_storage = NoteStorage::new(storage_items).unwrap();
let bytes = note_storage.to_bytes();
let parsed_note_storage = NoteStorage::read_from_bytes(&bytes).unwrap();
assert_eq!(note_storage, parsed_note_storage);
}
}