1use alloc::collections::BTreeMap;
2use alloc::collections::btree_map::Entry;
3use alloc::vec::Vec;
4
5use super::{
6 AccountDeltaError,
7 ByteReader,
8 ByteWriter,
9 Deserializable,
10 DeserializationError,
11 Serializable,
12 Word,
13};
14use crate::account::{StorageMap, StorageSlotContent, StorageSlotName, StorageSlotType};
15use crate::{EMPTY_WORD, Felt, LexicographicWord, ZERO};
16
17#[derive(Clone, Debug, PartialEq, Eq)]
24pub struct AccountStorageDelta {
25 deltas: BTreeMap<StorageSlotName, StorageSlotDelta>,
27}
28
29impl AccountStorageDelta {
30 pub fn new() -> Self {
32 Self { deltas: BTreeMap::new() }
33 }
34
35 pub fn from_raw(deltas: BTreeMap<StorageSlotName, StorageSlotDelta>) -> Self {
37 Self { deltas }
38 }
39
40 pub fn get(&self, slot_name: &StorageSlotName) -> Option<&StorageSlotDelta> {
42 self.deltas.get(slot_name)
43 }
44
45 pub(crate) fn slots(&self) -> impl Iterator<Item = (&StorageSlotName, &StorageSlotDelta)> {
47 self.deltas.iter()
48 }
49
50 pub fn values(&self) -> impl Iterator<Item = (&StorageSlotName, &Word)> {
52 self.deltas.iter().filter_map(|(slot_name, slot_delta)| match slot_delta {
53 StorageSlotDelta::Value(word) => Some((slot_name, word)),
54 StorageSlotDelta::Map(_) => None,
55 })
56 }
57
58 pub fn maps(&self) -> impl Iterator<Item = (&StorageSlotName, &StorageMapDelta)> {
60 self.deltas.iter().filter_map(|(slot_name, slot_delta)| match slot_delta {
61 StorageSlotDelta::Value(_) => None,
62 StorageSlotDelta::Map(map_delta) => Some((slot_name, map_delta)),
63 })
64 }
65
66 pub fn is_empty(&self) -> bool {
68 self.deltas.is_empty()
69 }
70
71 pub fn set_item(
81 &mut self,
82 slot_name: StorageSlotName,
83 new_slot_value: Word,
84 ) -> Result<(), AccountDeltaError> {
85 if !self.deltas.get(&slot_name).map(StorageSlotDelta::is_value).unwrap_or(true) {
86 return Err(AccountDeltaError::StorageSlotUsedAsDifferentTypes(slot_name));
87 }
88
89 self.deltas.insert(slot_name, StorageSlotDelta::Value(new_slot_value));
90
91 Ok(())
92 }
93
94 pub fn set_map_item(
104 &mut self,
105 slot_name: StorageSlotName,
106 key: Word,
107 new_value: Word,
108 ) -> Result<(), AccountDeltaError> {
109 match self
110 .deltas
111 .entry(slot_name.clone())
112 .or_insert(StorageSlotDelta::Map(StorageMapDelta::default()))
113 {
114 StorageSlotDelta::Value(_) => {
115 return Err(AccountDeltaError::StorageSlotUsedAsDifferentTypes(slot_name));
116 },
117 StorageSlotDelta::Map(storage_map_delta) => {
118 storage_map_delta.insert(key, new_value);
119 },
120 };
121
122 Ok(())
123 }
124
125 pub fn insert_empty_map_delta(&mut self, slot_name: StorageSlotName) {
131 self.deltas.insert(slot_name, StorageSlotDelta::with_empty_map());
132 }
133
134 pub fn merge(&mut self, other: Self) -> Result<(), AccountDeltaError> {
136 for (slot_name, slot_delta) in other.deltas {
137 match self.deltas.entry(slot_name.clone()) {
138 Entry::Vacant(vacant_entry) => {
139 vacant_entry.insert(slot_delta);
140 },
141 Entry::Occupied(mut occupied_entry) => {
142 occupied_entry.get_mut().merge(slot_delta).ok_or_else(|| {
143 AccountDeltaError::StorageSlotUsedAsDifferentTypes(slot_name)
144 })?;
145 },
146 }
147 }
148
149 Ok(())
150 }
151
152 fn cleared_values(&self) -> impl Iterator<Item = &StorageSlotName> {
154 self.values().filter_map(
155 |(slot_name, slot_value)| {
156 if slot_value.is_empty() { Some(slot_name) } else { None }
157 },
158 )
159 }
160
161 fn updated_values(&self) -> impl Iterator<Item = (&StorageSlotName, &Word)> {
163 self.values().filter_map(|(slot_name, slot_value)| {
164 if !slot_value.is_empty() {
165 Some((slot_name, slot_value))
166 } else {
167 None
168 }
169 })
170 }
171
172 pub(super) fn append_delta_elements(&self, elements: &mut Vec<Felt>) {
175 const DOMAIN_VALUE: Felt = Felt::new(2);
176 const DOMAIN_MAP: Felt = Felt::new(3);
177
178 for (slot_name, slot_delta) in self.deltas.iter() {
179 let slot_id = slot_name.id();
180
181 match slot_delta {
182 StorageSlotDelta::Value(new_value) => {
183 elements.extend_from_slice(&[
184 DOMAIN_VALUE,
185 ZERO,
186 slot_id.suffix(),
187 slot_id.prefix(),
188 ]);
189 elements.extend_from_slice(new_value.as_elements());
190 },
191 StorageSlotDelta::Map(map_delta) => {
192 for (key, value) in map_delta.entries() {
193 elements.extend_from_slice(key.inner().as_elements());
194 elements.extend_from_slice(value.as_elements());
195 }
196
197 let num_changed_entries = Felt::try_from(map_delta.num_entries()).expect(
198 "number of changed entries should not exceed max representable felt",
199 );
200
201 elements.extend_from_slice(&[
202 DOMAIN_MAP,
203 num_changed_entries,
204 slot_id.suffix(),
205 slot_id.prefix(),
206 ]);
207 elements.extend_from_slice(EMPTY_WORD.as_elements());
208 },
209 }
210 }
211 }
212
213 pub fn into_map(self) -> BTreeMap<StorageSlotName, StorageSlotDelta> {
215 self.deltas
216 }
217}
218
219impl Default for AccountStorageDelta {
220 fn default() -> Self {
221 Self::new()
222 }
223}
224
225impl Serializable for AccountStorageDelta {
226 fn write_into<W: ByteWriter>(&self, target: &mut W) {
227 let num_cleared_values = self.cleared_values().count();
228 let num_cleared_values =
229 u8::try_from(num_cleared_values).expect("number of slots should fit in u8");
230 let cleared_values = self.cleared_values();
231
232 let num_updated_values = self.updated_values().count();
233 let num_updated_values =
234 u8::try_from(num_updated_values).expect("number of slots should fit in u8");
235 let updated_values = self.updated_values();
236
237 let num_maps = self.maps().count();
238 let num_maps = u8::try_from(num_maps).expect("number of slots should fit in u8");
239 let maps = self.maps();
240
241 target.write_u8(num_cleared_values);
242 target.write_many(cleared_values);
243
244 target.write_u8(num_updated_values);
245 target.write_many(updated_values);
246
247 target.write_u8(num_maps);
248 target.write_many(maps);
249 }
250
251 fn get_size_hint(&self) -> usize {
252 let u8_size = 0u8.get_size_hint();
253
254 let mut storage_map_delta_size = 0;
255 for (slot_name, storage_map_delta) in self.maps() {
256 storage_map_delta_size += slot_name.get_size_hint() + storage_map_delta.get_size_hint();
259 }
260
261 u8_size * 3 +
263 self.cleared_values().fold(0, |acc, slot_name| acc + slot_name.get_size_hint()) +
265 self.updated_values().fold(0, |acc, (slot_name, slot_value)| {
267 acc + slot_name.get_size_hint() + slot_value.get_size_hint()
268 }) +
269 storage_map_delta_size
271 }
272}
273
274impl Deserializable for AccountStorageDelta {
275 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
276 let mut deltas = BTreeMap::new();
277
278 let num_cleared_values = source.read_u8()?;
279 for _ in 0..num_cleared_values {
280 let cleared_value: StorageSlotName = source.read()?;
281 deltas.insert(cleared_value, StorageSlotDelta::with_empty_value());
282 }
283
284 let num_updated_values = source.read_u8()?;
285 for _ in 0..num_updated_values {
286 let (updated_slot, updated_value) = source.read()?;
287 deltas.insert(updated_slot, StorageSlotDelta::Value(updated_value));
288 }
289
290 let num_maps = source.read_u8()? as usize;
291 deltas.extend(
292 source
293 .read_many::<(StorageSlotName, StorageMapDelta)>(num_maps)?
294 .into_iter()
295 .map(|(slot_name, map_delta)| (slot_name, StorageSlotDelta::Map(map_delta))),
296 );
297
298 Ok(Self::from_raw(deltas))
299 }
300}
301
302#[derive(Debug, Clone, PartialEq, Eq)]
311pub enum StorageSlotDelta {
312 Value(Word),
313 Map(StorageMapDelta),
314}
315
316impl StorageSlotDelta {
317 const VALUE: u8 = 0;
322
323 const MAP: u8 = 1;
325
326 pub fn with_empty_value() -> Self {
331 Self::Value(Word::empty())
332 }
333
334 pub fn with_empty_map() -> Self {
336 Self::Map(StorageMapDelta::default())
337 }
338
339 pub fn slot_type(&self) -> StorageSlotType {
344 match self {
345 StorageSlotDelta::Value(_) => StorageSlotType::Value,
346 StorageSlotDelta::Map(_) => StorageSlotType::Map,
347 }
348 }
349
350 pub fn is_value(&self) -> bool {
352 matches!(self, Self::Value(_))
353 }
354
355 pub fn is_map(&self) -> bool {
357 matches!(self, Self::Map(_))
358 }
359
360 pub fn unwrap_value(self) -> Word {
370 match self {
371 StorageSlotDelta::Value(value) => value,
372 StorageSlotDelta::Map(_) => panic!("called unwrap_value on a map slot delta"),
373 }
374 }
375
376 pub fn unwrap_map(self) -> StorageMapDelta {
383 match self {
384 StorageSlotDelta::Value(_) => panic!("called unwrap_map on a value slot delta"),
385 StorageSlotDelta::Map(map_delta) => map_delta,
386 }
387 }
388
389 #[must_use]
396 fn merge(&mut self, other: Self) -> Option<()> {
397 match (self, other) {
398 (StorageSlotDelta::Value(current_value), StorageSlotDelta::Value(new_value)) => {
399 *current_value = new_value;
400 },
401 (StorageSlotDelta::Map(current_map_delta), StorageSlotDelta::Map(new_map_delta)) => {
402 current_map_delta.merge(new_map_delta);
403 },
404 (..) => {
405 return None;
406 },
407 }
408
409 Some(())
410 }
411}
412
413impl From<StorageSlotContent> for StorageSlotDelta {
414 fn from(content: StorageSlotContent) -> Self {
415 match content {
416 StorageSlotContent::Value(word) => StorageSlotDelta::Value(word),
417 StorageSlotContent::Map(storage_map) => {
418 StorageSlotDelta::Map(StorageMapDelta::from(storage_map))
419 },
420 }
421 }
422}
423
424impl Serializable for StorageSlotDelta {
425 fn write_into<W: ByteWriter>(&self, target: &mut W) {
426 match self {
427 StorageSlotDelta::Value(value) => {
428 target.write_u8(Self::VALUE);
429 target.write(value);
430 },
431 StorageSlotDelta::Map(storage_map_delta) => {
432 target.write_u8(Self::MAP);
433 target.write(storage_map_delta);
434 },
435 }
436 }
437}
438
439impl Deserializable for StorageSlotDelta {
440 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
441 match source.read_u8()? {
442 Self::VALUE => {
443 let value = source.read()?;
444 Ok(Self::Value(value))
445 },
446 Self::MAP => {
447 let map_delta = source.read()?;
448 Ok(Self::Map(map_delta))
449 },
450 other => Err(DeserializationError::InvalidValue(format!(
451 "unknown storage slot delta variant {other}"
452 ))),
453 }
454 }
455}
456
457#[derive(Clone, Debug, Default, PartialEq, Eq)]
468pub struct StorageMapDelta(BTreeMap<LexicographicWord, Word>);
469
470impl StorageMapDelta {
471 pub fn new(map: BTreeMap<LexicographicWord, Word>) -> Self {
473 Self(map)
474 }
475
476 pub fn num_entries(&self) -> usize {
478 self.0.len()
479 }
480
481 pub fn entries(&self) -> &BTreeMap<LexicographicWord, Word> {
485 &self.0
486 }
487
488 pub fn insert(&mut self, raw_key: Word, value: Word) {
490 self.0.insert(LexicographicWord::new(raw_key), value);
491 }
492
493 pub fn is_empty(&self) -> bool {
495 self.0.is_empty()
496 }
497
498 pub fn merge(&mut self, other: Self) {
500 self.0.extend(other.0);
502 }
503
504 pub fn as_map_mut(&mut self) -> &mut BTreeMap<LexicographicWord, Word> {
506 &mut self.0
507 }
508
509 fn cleared_keys(&self) -> impl Iterator<Item = &Word> + '_ {
511 self.0.iter().filter(|&(_, value)| value.is_empty()).map(|(key, _)| key.inner())
512 }
513
514 fn updated_entries(&self) -> impl Iterator<Item = (&Word, &Word)> + '_ {
516 self.0.iter().filter_map(|(key, value)| {
517 if !value.is_empty() {
518 Some((key.inner(), value))
519 } else {
520 None
521 }
522 })
523 }
524}
525
526#[cfg(any(feature = "testing", test))]
527impl StorageMapDelta {
528 pub fn from_iters(
530 cleared_leaves: impl IntoIterator<Item = Word>,
531 updated_leaves: impl IntoIterator<Item = (Word, Word)>,
532 ) -> Self {
533 Self(BTreeMap::from_iter(
534 cleared_leaves
535 .into_iter()
536 .map(|key| (LexicographicWord::new(key), EMPTY_WORD))
537 .chain(
538 updated_leaves
539 .into_iter()
540 .map(|(key, value)| (LexicographicWord::new(key), value)),
541 ),
542 ))
543 }
544
545 pub fn into_map(self) -> BTreeMap<LexicographicWord, Word> {
547 self.0
548 }
549}
550
551impl From<StorageMap> for StorageMapDelta {
553 fn from(map: StorageMap) -> Self {
554 StorageMapDelta::new(
555 map.into_entries()
556 .into_iter()
557 .map(|(key, value)| (LexicographicWord::new(key), value))
558 .collect(),
559 )
560 }
561}
562
563impl Serializable for StorageMapDelta {
564 fn write_into<W: ByteWriter>(&self, target: &mut W) {
565 let cleared: Vec<&Word> = self.cleared_keys().collect();
566 let updated: Vec<(&Word, &Word)> = self.updated_entries().collect();
567
568 target.write_usize(cleared.len());
569 target.write_many(cleared.iter());
570
571 target.write_usize(updated.len());
572 target.write_many(updated.iter());
573 }
574
575 fn get_size_hint(&self) -> usize {
576 let word_size = EMPTY_WORD.get_size_hint();
577
578 let cleared_keys_count = self.cleared_keys().count();
579 let updated_entries_count = self.updated_entries().count();
580
581 cleared_keys_count.get_size_hint() +
583 cleared_keys_count * Word::SERIALIZED_SIZE +
584
585 updated_entries_count.get_size_hint() +
587 updated_entries_count * (Word::SERIALIZED_SIZE + word_size)
588 }
589}
590
591impl Deserializable for StorageMapDelta {
592 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
593 let mut map = BTreeMap::new();
594
595 let cleared_count = source.read_usize()?;
596 for _ in 0..cleared_count {
597 let cleared_key = source.read()?;
598 map.insert(LexicographicWord::new(cleared_key), EMPTY_WORD);
599 }
600
601 let updated_count = source.read_usize()?;
602 for _ in 0..updated_count {
603 let (updated_key, updated_value) = source.read()?;
604 map.insert(LexicographicWord::new(updated_key), updated_value);
605 }
606
607 Ok(Self::new(map))
608 }
609}
610
611#[cfg(test)]
615mod tests {
616 use anyhow::Context;
617 use assert_matches::assert_matches;
618
619 use super::{AccountStorageDelta, Deserializable, Serializable};
620 use crate::account::{StorageMapDelta, StorageSlotDelta, StorageSlotName};
621 use crate::errors::AccountDeltaError;
622 use crate::{ONE, Word};
623
624 #[test]
625 fn account_storage_delta_returns_err_on_slot_type_mismatch() {
626 let value_slot_name = StorageSlotName::mock(1);
627 let map_slot_name = StorageSlotName::mock(2);
628
629 let mut delta = AccountStorageDelta::from_iters(
630 [value_slot_name.clone()],
631 [],
632 [(map_slot_name.clone(), StorageMapDelta::default())],
633 );
634
635 let err = delta
636 .set_map_item(value_slot_name.clone(), Word::empty(), Word::empty())
637 .unwrap_err();
638 assert_matches!(err, AccountDeltaError::StorageSlotUsedAsDifferentTypes(slot_name) => {
639 assert_eq!(value_slot_name, slot_name)
640 });
641
642 let err = delta.set_item(map_slot_name.clone(), Word::empty()).unwrap_err();
643 assert_matches!(err, AccountDeltaError::StorageSlotUsedAsDifferentTypes(slot_name) => {
644 assert_eq!(map_slot_name, slot_name)
645 });
646 }
647
648 #[test]
649 fn test_is_empty() {
650 let storage_delta = AccountStorageDelta::new();
651 assert!(storage_delta.is_empty());
652
653 let storage_delta = AccountStorageDelta::from_iters([StorageSlotName::mock(1)], [], []);
654 assert!(!storage_delta.is_empty());
655
656 let storage_delta = AccountStorageDelta::from_iters(
657 [],
658 [(StorageSlotName::mock(2), Word::from([ONE, ONE, ONE, ONE]))],
659 [],
660 );
661 assert!(!storage_delta.is_empty());
662
663 let storage_delta = AccountStorageDelta::from_iters(
664 [],
665 [],
666 [(StorageSlotName::mock(3), StorageMapDelta::default())],
667 );
668 assert!(!storage_delta.is_empty());
669 }
670
671 #[test]
672 fn test_serde_account_storage_delta() {
673 let storage_delta = AccountStorageDelta::new();
674 let serialized = storage_delta.to_bytes();
675 let deserialized = AccountStorageDelta::read_from_bytes(&serialized).unwrap();
676 assert_eq!(deserialized, storage_delta);
677
678 let storage_delta = AccountStorageDelta::from_iters([StorageSlotName::mock(1)], [], []);
679 let serialized = storage_delta.to_bytes();
680 let deserialized = AccountStorageDelta::read_from_bytes(&serialized).unwrap();
681 assert_eq!(deserialized, storage_delta);
682
683 let storage_delta = AccountStorageDelta::from_iters(
684 [],
685 [(StorageSlotName::mock(2), Word::from([ONE, ONE, ONE, ONE]))],
686 [],
687 );
688 let serialized = storage_delta.to_bytes();
689 let deserialized = AccountStorageDelta::read_from_bytes(&serialized).unwrap();
690 assert_eq!(deserialized, storage_delta);
691
692 let storage_delta = AccountStorageDelta::from_iters(
693 [],
694 [],
695 [(StorageSlotName::mock(3), StorageMapDelta::default())],
696 );
697 let serialized = storage_delta.to_bytes();
698 let deserialized = AccountStorageDelta::read_from_bytes(&serialized).unwrap();
699 assert_eq!(deserialized, storage_delta);
700 }
701
702 #[test]
703 fn test_serde_storage_map_delta() {
704 let storage_map_delta = StorageMapDelta::default();
705 let serialized = storage_map_delta.to_bytes();
706 let deserialized = StorageMapDelta::read_from_bytes(&serialized).unwrap();
707 assert_eq!(deserialized, storage_map_delta);
708
709 let storage_map_delta = StorageMapDelta::from_iters([Word::from([ONE, ONE, ONE, ONE])], []);
710 let serialized = storage_map_delta.to_bytes();
711 let deserialized = StorageMapDelta::read_from_bytes(&serialized).unwrap();
712 assert_eq!(deserialized, storage_map_delta);
713
714 let storage_map_delta =
715 StorageMapDelta::from_iters([], [(Word::empty(), Word::from([ONE, ONE, ONE, ONE]))]);
716 let serialized = storage_map_delta.to_bytes();
717 let deserialized = StorageMapDelta::read_from_bytes(&serialized).unwrap();
718 assert_eq!(deserialized, storage_map_delta);
719 }
720
721 #[test]
722 fn test_serde_storage_slot_value_delta() {
723 let slot_delta = StorageSlotDelta::with_empty_value();
724 let serialized = slot_delta.to_bytes();
725 let deserialized = StorageSlotDelta::read_from_bytes(&serialized).unwrap();
726 assert_eq!(deserialized, slot_delta);
727
728 let slot_delta = StorageSlotDelta::Value(Word::from([1, 2, 3, 4u32]));
729 let serialized = slot_delta.to_bytes();
730 let deserialized = StorageSlotDelta::read_from_bytes(&serialized).unwrap();
731 assert_eq!(deserialized, slot_delta);
732 }
733
734 #[test]
735 fn test_serde_storage_slot_map_delta() {
736 let slot_delta = StorageSlotDelta::with_empty_map();
737 let serialized = slot_delta.to_bytes();
738 let deserialized = StorageSlotDelta::read_from_bytes(&serialized).unwrap();
739 assert_eq!(deserialized, slot_delta);
740
741 let map_delta = StorageMapDelta::from_iters(
742 [Word::from([1, 2, 3, 4u32])],
743 [(Word::from([5, 6, 7, 8u32]), Word::from([3, 4, 5, 6u32]))],
744 );
745 let slot_delta = StorageSlotDelta::Map(map_delta);
746 let serialized = slot_delta.to_bytes();
747 let deserialized = StorageSlotDelta::read_from_bytes(&serialized).unwrap();
748 assert_eq!(deserialized, slot_delta);
749 }
750
751 #[rstest::rstest]
752 #[case::some_some(Some(1), Some(2), Some(2))]
753 #[case::none_some(None, Some(2), Some(2))]
754 #[case::some_none(Some(1), None, None)]
755 #[test]
756 fn merge_items(
757 #[case] x: Option<u32>,
758 #[case] y: Option<u32>,
759 #[case] expected: Option<u32>,
760 ) -> anyhow::Result<()> {
761 fn create_delta(item: Option<u32>) -> AccountStorageDelta {
763 let slot_name = StorageSlotName::mock(123);
764 let item = item.map(|x| (slot_name.clone(), Word::from([x, 0, 0, 0])));
765
766 AccountStorageDelta::new()
767 .add_cleared_items(item.is_none().then_some(slot_name.clone()))
768 .add_updated_values(item)
769 }
770
771 let mut delta_x = create_delta(x);
772 let delta_y = create_delta(y);
773 let expected = create_delta(expected);
774
775 delta_x.merge(delta_y).context("failed to merge deltas")?;
776
777 assert_eq!(delta_x, expected);
778
779 Ok(())
780 }
781
782 #[rstest::rstest]
783 #[case::some_some(Some(1), Some(2), Some(2))]
784 #[case::none_some(None, Some(2), Some(2))]
785 #[case::some_none(Some(1), None, None)]
786 #[test]
787 fn merge_maps(#[case] x: Option<u32>, #[case] y: Option<u32>, #[case] expected: Option<u32>) {
788 fn create_delta(value: Option<u32>) -> StorageMapDelta {
789 let key = Word::from([10u32, 0, 0, 0]);
790 match value {
791 Some(value) => {
792 StorageMapDelta::from_iters([], [(key, Word::from([value, 0, 0, 0]))])
793 },
794 None => StorageMapDelta::from_iters([key], []),
795 }
796 }
797
798 let mut delta_x = create_delta(x);
799 let delta_y = create_delta(y);
800 let expected = create_delta(expected);
801
802 delta_x.merge(delta_y);
803
804 assert_eq!(delta_x, expected);
805 }
806}