Skip to main content

miden_protocol/note/
storage.rs

1use alloc::vec::Vec;
2
3use crate::errors::NoteError;
4use crate::utils::serde::{
5    ByteReader,
6    ByteWriter,
7    Deserializable,
8    DeserializationError,
9    Serializable,
10};
11use crate::{Felt, Hasher, MAX_NOTE_STORAGE_ITEMS, Word};
12
13// NOTE STORAGE
14// ================================================================================================
15
16/// A container for note storage items.
17///
18/// A note can be associated with up to 1024 storage items. Each item is represented by a single
19/// field element. Thus, note storage can contain up to ~8 KB of data.
20///
21/// All storage items associated with a note can be reduced to a single commitment which is
22/// computed as an RPO256 hash over the storage elements.
23#[derive(Clone, Debug)]
24pub struct NoteStorage {
25    items: Vec<Felt>,
26    commitment: Word,
27}
28
29impl NoteStorage {
30    // CONSTRUCTOR
31    // --------------------------------------------------------------------------------------------
32
33    /// Returns [NoteStorage] instantiated from the provided items.
34    ///
35    /// # Errors
36    /// Returns an error if the number of provided storage items is greater than 1024.
37    pub fn new(items: Vec<Felt>) -> Result<Self, NoteError> {
38        if items.len() > MAX_NOTE_STORAGE_ITEMS {
39            return Err(NoteError::TooManyStorageItems(items.len()));
40        }
41
42        let commitment = Hasher::hash_elements(&items);
43
44        Ok(Self { items, commitment })
45    }
46
47    // PUBLIC ACCESSORS
48    // --------------------------------------------------------------------------------------------
49
50    /// Returns a commitment to this storage.
51    pub fn commitment(&self) -> Word {
52        self.commitment
53    }
54
55    /// Returns the number of storage items.
56    ///
57    /// The returned value is guaranteed to be smaller than or equal to [`MAX_NOTE_STORAGE_ITEMS`].
58    pub fn num_items(&self) -> u16 {
59        const _: () = assert!(MAX_NOTE_STORAGE_ITEMS <= u16::MAX as usize);
60        debug_assert!(
61            self.items.len() <= MAX_NOTE_STORAGE_ITEMS,
62            "The constructor should have checked the number of storage items"
63        );
64        self.items.len() as u16
65    }
66
67    /// Returns `true` if the storage has no items.
68    pub fn is_empty(&self) -> bool {
69        self.items.is_empty()
70    }
71
72    /// Returns a reference to the storage items.
73    pub fn items(&self) -> &[Felt] {
74        &self.items
75    }
76
77    /// Returns the note's storage as a vector of field elements.
78    pub fn to_elements(&self) -> Vec<Felt> {
79        self.items.to_vec()
80    }
81}
82
83impl Default for NoteStorage {
84    fn default() -> Self {
85        Self::new(vec![]).expect("empty storage should be valid")
86    }
87}
88
89impl PartialEq for NoteStorage {
90    fn eq(&self, other: &Self) -> bool {
91        let NoteStorage { items, commitment: _ } = self;
92        items == &other.items
93    }
94}
95
96impl Eq for NoteStorage {}
97
98// CONVERSION
99// ================================================================================================
100
101impl From<NoteStorage> for Vec<Felt> {
102    fn from(value: NoteStorage) -> Self {
103        value.items
104    }
105}
106
107impl TryFrom<Vec<Felt>> for NoteStorage {
108    type Error = NoteError;
109
110    fn try_from(value: Vec<Felt>) -> Result<Self, Self::Error> {
111        NoteStorage::new(value)
112    }
113}
114
115// SERIALIZATION
116// ================================================================================================
117
118impl Serializable for NoteStorage {
119    fn write_into<W: ByteWriter>(&self, target: &mut W) {
120        let NoteStorage { items, commitment: _commitment } = self;
121        target.write_u16(items.len().try_into().expect("storage items len is not a u16 value"));
122        target.write_many(items);
123    }
124}
125
126impl Deserializable for NoteStorage {
127    fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
128        let len = source.read_u16()? as usize;
129        let items = source.read_many::<Felt>(len)?;
130        Self::new(items).map_err(|v| DeserializationError::InvalidValue(format!("{v}")))
131    }
132}
133
134// TESTS
135// ================================================================================================
136
137#[cfg(test)]
138mod tests {
139    use miden_crypto::utils::Deserializable;
140
141    use super::{Felt, NoteStorage, Serializable};
142
143    #[test]
144    fn test_storage_item_ordering() {
145        // storage items are provided in reverse stack order
146        let storage_items = vec![Felt::new(1), Felt::new(2), Felt::new(3)];
147        // we expect the storage items to remain in reverse stack order.
148        let expected_ordering = vec![Felt::new(1), Felt::new(2), Felt::new(3)];
149
150        let note_storage = NoteStorage::new(storage_items).expect("note created should succeed");
151        assert_eq!(&expected_ordering, note_storage.items());
152    }
153
154    #[test]
155    fn test_storage_serialization() {
156        let storage_items = vec![Felt::new(1), Felt::new(2), Felt::new(3)];
157        let note_storage = NoteStorage::new(storage_items).unwrap();
158
159        let bytes = note_storage.to_bytes();
160        let parsed_note_storage = NoteStorage::read_from_bytes(&bytes).unwrap();
161        assert_eq!(note_storage, parsed_note_storage);
162    }
163}