1use alloc::collections::BTreeMap;
2use alloc::collections::btree_map::Entry;
3use alloc::string::ToString;
4use alloc::vec::Vec;
5
6use super::{
7 AccountDeltaError,
8 ByteReader,
9 ByteWriter,
10 Deserializable,
11 DeserializationError,
12 Serializable,
13 Word,
14};
15use crate::account::{StorageMap, StorageSlotType};
16use crate::{EMPTY_WORD, Felt, LexicographicWord, ZERO};
17
18#[derive(Clone, Debug, PartialEq, Eq)]
29pub struct AccountStorageDelta {
30 values: BTreeMap<u8, Word>,
32 maps: BTreeMap<u8, StorageMapDelta>,
34}
35
36impl AccountStorageDelta {
37 pub fn new() -> Self {
39 Self {
40 values: BTreeMap::new(),
41 maps: BTreeMap::new(),
42 }
43 }
44
45 pub fn from_parts(
53 values: BTreeMap<u8, Word>,
54 maps: BTreeMap<u8, StorageMapDelta>,
55 ) -> Result<Self, AccountDeltaError> {
56 let delta = Self { values, maps };
57 delta.validate()?;
58
59 Ok(delta)
60 }
61
62 pub(crate) fn slot_type(&self, slot_index: u8) -> Option<StorageSlotType> {
64 if self.values().contains_key(&slot_index) {
65 Some(StorageSlotType::Value)
66 } else if self.maps().contains_key(&slot_index) {
67 Some(StorageSlotType::Map)
68 } else {
69 None
70 }
71 }
72
73 pub fn values(&self) -> &BTreeMap<u8, Word> {
75 &self.values
76 }
77
78 pub fn maps(&self) -> &BTreeMap<u8, StorageMapDelta> {
80 &self.maps
81 }
82
83 pub fn is_empty(&self) -> bool {
85 self.values.is_empty() && self.maps.is_empty()
86 }
87
88 pub fn set_item(&mut self, slot_index: u8, new_slot_value: Word) {
90 self.values.insert(slot_index, new_slot_value);
91 }
92
93 pub fn set_map_item(&mut self, slot_index: u8, key: Word, new_value: Word) {
95 self.maps.entry(slot_index).or_default().insert(key, new_value);
96 }
97
98 pub fn merge(&mut self, other: Self) -> Result<(), AccountDeltaError> {
100 self.values.extend(other.values);
101
102 for (slot, update) in other.maps.into_iter() {
104 match self.maps.entry(slot) {
105 Entry::Vacant(entry) => {
106 entry.insert(update);
107 },
108 Entry::Occupied(mut entry) => entry.get_mut().merge(update),
109 }
110 }
111
112 self.validate()
113 }
114
115 fn validate(&self) -> Result<(), AccountDeltaError> {
123 for slot in self.maps.keys() {
124 if self.values.contains_key(slot) {
125 return Err(AccountDeltaError::StorageSlotUsedAsDifferentTypes(*slot));
126 }
127 }
128
129 Ok(())
130 }
131
132 fn cleared_slots(&self) -> impl Iterator<Item = u8> + '_ {
134 self.values.iter().filter(|&(_, value)| value.is_empty()).map(|(slot, _)| *slot)
135 }
136
137 fn updated_slots(&self) -> impl Iterator<Item = (&u8, &Word)> + '_ {
139 self.values.iter().filter(|&(_, value)| !value.is_empty())
140 }
141
142 pub(super) fn append_delta_elements(&self, elements: &mut Vec<Felt>) {
145 const DOMAIN_VALUE: Felt = Felt::new(2);
146 const DOMAIN_MAP: Felt = Felt::new(3);
147
148 let highest_value_slot_idx = self.values.last_key_value().map(|(slot_idx, _)| slot_idx);
149 let highest_map_slot_idx = self.maps.last_key_value().map(|(slot_idx, _)| slot_idx);
150 let highest_slot_idx =
151 highest_value_slot_idx.max(highest_map_slot_idx).copied().unwrap_or(0);
152
153 for slot_idx in 0..=highest_slot_idx {
154 let slot_idx_felt = Felt::from(slot_idx);
155
156 match self.values.get(&slot_idx) {
159 Some(new_value) => {
160 elements.extend_from_slice(&[DOMAIN_VALUE, slot_idx_felt, ZERO, ZERO]);
161 elements.extend_from_slice(new_value.as_elements());
162 },
163 None => {
164 if let Some(map_delta) = self.maps().get(&slot_idx) {
165 if map_delta.is_empty() {
166 continue;
167 }
168
169 for (key, value) in map_delta.entries() {
170 elements.extend_from_slice(key.inner().as_elements());
171 elements.extend_from_slice(value.as_elements());
172 }
173
174 let num_changed_entries = Felt::try_from(map_delta.num_entries()).expect(
175 "number of changed entries should not exceed max representable felt",
176 );
177
178 elements.extend_from_slice(&[
179 DOMAIN_MAP,
180 slot_idx_felt,
181 num_changed_entries,
182 ZERO,
183 ]);
184 elements.extend_from_slice(EMPTY_WORD.as_elements());
185 }
186 },
187 }
188 }
189 }
190
191 pub fn into_parts(self) -> (BTreeMap<u8, Word>, BTreeMap<u8, StorageMapDelta>) {
193 (self.values, self.maps)
194 }
195}
196
197impl Default for AccountStorageDelta {
198 fn default() -> Self {
199 Self::new()
200 }
201}
202
203#[cfg(any(feature = "testing", test))]
204impl AccountStorageDelta {
205 pub fn from_iters(
207 cleared_values: impl IntoIterator<Item = u8>,
208 updated_values: impl IntoIterator<Item = (u8, Word)>,
209 updated_maps: impl IntoIterator<Item = (u8, StorageMapDelta)>,
210 ) -> Self {
211 Self {
212 values: BTreeMap::from_iter(
213 cleared_values.into_iter().map(|key| (key, EMPTY_WORD)).chain(updated_values),
214 ),
215 maps: BTreeMap::from_iter(updated_maps),
216 }
217 }
218}
219
220impl Serializable for AccountStorageDelta {
221 fn write_into<W: ByteWriter>(&self, target: &mut W) {
222 let cleared: Vec<u8> = self.cleared_slots().collect();
223 let updated: Vec<(&u8, &Word)> = self.updated_slots().collect();
224
225 target.write_u8(cleared.len() as u8);
226 target.write_many(cleared.iter());
227
228 target.write_u8(updated.len() as u8);
229 target.write_many(updated.iter());
230
231 target.write_u8(self.maps.len() as u8);
232 target.write_many(self.maps.iter());
233 }
234
235 fn get_size_hint(&self) -> usize {
236 let u8_size = 0u8.get_size_hint();
237 let word_size = EMPTY_WORD.get_size_hint();
238
239 let mut storage_map_delta_size = 0;
240 for (slot, storage_map_delta) in self.maps.iter() {
241 storage_map_delta_size += slot.get_size_hint() + storage_map_delta.get_size_hint();
244 }
245
246 u8_size * 3 +
248 self.cleared_slots().count() * u8_size +
250 self.updated_slots().count() * (u8_size + word_size) +
252 storage_map_delta_size
254 }
255}
256
257impl Deserializable for AccountStorageDelta {
258 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
259 let mut values = BTreeMap::new();
260
261 let num_cleared_items = source.read_u8()? as usize;
262 for _ in 0..num_cleared_items {
263 let cleared_slot = source.read_u8()?;
264 values.insert(cleared_slot, EMPTY_WORD);
265 }
266
267 let num_updated_items = source.read_u8()? as usize;
268 for _ in 0..num_updated_items {
269 let (updated_slot, updated_value) = source.read()?;
270 values.insert(updated_slot, updated_value);
271 }
272
273 let num_maps = source.read_u8()? as usize;
274 let maps = source.read_many::<(u8, StorageMapDelta)>(num_maps)?.into_iter().collect();
275
276 Self::from_parts(values, maps)
277 .map_err(|err| DeserializationError::InvalidValue(err.to_string()))
278 }
279}
280
281#[derive(Clone, Debug, Default, PartialEq, Eq)]
292pub struct StorageMapDelta(BTreeMap<LexicographicWord, Word>);
293
294impl StorageMapDelta {
295 pub fn new(map: BTreeMap<LexicographicWord, Word>) -> Self {
297 Self(map)
298 }
299
300 pub fn num_entries(&self) -> usize {
302 self.0.len()
303 }
304
305 pub fn entries(&self) -> &BTreeMap<LexicographicWord, Word> {
309 &self.0
310 }
311
312 pub fn insert(&mut self, raw_key: Word, value: Word) {
314 self.0.insert(LexicographicWord::new(raw_key), value);
315 }
316
317 pub fn is_empty(&self) -> bool {
319 self.0.is_empty()
320 }
321
322 pub fn merge(&mut self, other: Self) {
324 self.0.extend(other.0);
326 }
327
328 pub fn as_map_mut(&mut self) -> &mut BTreeMap<LexicographicWord, Word> {
330 &mut self.0
331 }
332
333 fn cleared_keys(&self) -> impl Iterator<Item = &Word> + '_ {
335 self.0.iter().filter(|&(_, value)| value.is_empty()).map(|(key, _)| key.inner())
336 }
337
338 fn updated_entries(&self) -> impl Iterator<Item = (&Word, &Word)> + '_ {
340 self.0.iter().filter_map(|(key, value)| {
341 if !value.is_empty() {
342 Some((key.inner(), value))
343 } else {
344 None
345 }
346 })
347 }
348}
349
350#[cfg(any(feature = "testing", test))]
351impl StorageMapDelta {
352 pub fn from_iters(
354 cleared_leaves: impl IntoIterator<Item = Word>,
355 updated_leaves: impl IntoIterator<Item = (Word, Word)>,
356 ) -> Self {
357 Self(BTreeMap::from_iter(
358 cleared_leaves
359 .into_iter()
360 .map(|key| (LexicographicWord::new(key), EMPTY_WORD))
361 .chain(
362 updated_leaves
363 .into_iter()
364 .map(|(key, value)| (LexicographicWord::new(key), value)),
365 ),
366 ))
367 }
368
369 pub fn into_map(self) -> BTreeMap<LexicographicWord, Word> {
371 self.0
372 }
373}
374
375impl From<StorageMap> for StorageMapDelta {
377 fn from(map: StorageMap) -> Self {
378 StorageMapDelta::new(
379 map.into_entries()
380 .into_iter()
381 .map(|(key, value)| (LexicographicWord::new(key), value))
382 .collect(),
383 )
384 }
385}
386
387impl Serializable for StorageMapDelta {
388 fn write_into<W: ByteWriter>(&self, target: &mut W) {
389 let cleared: Vec<&Word> = self.cleared_keys().collect();
390 let updated: Vec<(&Word, &Word)> = self.updated_entries().collect();
391
392 target.write_usize(cleared.len());
393 target.write_many(cleared.iter());
394
395 target.write_usize(updated.len());
396 target.write_many(updated.iter());
397 }
398
399 fn get_size_hint(&self) -> usize {
400 let word_size = EMPTY_WORD.get_size_hint();
401
402 let cleared_keys_count = self.cleared_keys().count();
403 let updated_entries_count = self.updated_entries().count();
404
405 cleared_keys_count.get_size_hint() +
407 cleared_keys_count * Word::SERIALIZED_SIZE +
408
409 updated_entries_count.get_size_hint() +
411 updated_entries_count * (Word::SERIALIZED_SIZE + word_size)
412 }
413}
414
415impl Deserializable for StorageMapDelta {
416 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
417 let mut map = BTreeMap::new();
418
419 let cleared_count = source.read_usize()?;
420 for _ in 0..cleared_count {
421 let cleared_key = source.read()?;
422 map.insert(LexicographicWord::new(cleared_key), EMPTY_WORD);
423 }
424
425 let updated_count = source.read_usize()?;
426 for _ in 0..updated_count {
427 let (updated_key, updated_value) = source.read()?;
428 map.insert(LexicographicWord::new(updated_key), updated_value);
429 }
430
431 Ok(Self::new(map))
432 }
433}
434
435#[cfg(test)]
439mod tests {
440 use anyhow::Context;
441
442 use super::{AccountStorageDelta, Deserializable, Serializable};
443 use crate::account::StorageMapDelta;
444 use crate::testing::storage::AccountStorageDeltaBuilder;
445 use crate::{ONE, Word, ZERO};
446
447 #[test]
448 fn account_storage_delta_validation() {
449 let delta = AccountStorageDelta::from_iters(
450 [1, 2, 3],
451 [(4, Word::from([ONE, ONE, ONE, ONE])), (5, Word::from([ONE, ONE, ONE, ZERO]))],
452 [],
453 );
454 assert!(delta.validate().is_ok());
455
456 let bytes = delta.to_bytes();
457 assert_eq!(AccountStorageDelta::read_from_bytes(&bytes), Ok(delta));
458
459 let delta = AccountStorageDelta::from_iters(
461 [1, 2, 3],
462 [(2, Word::from([ONE, ONE, ONE, ONE])), (5, Word::from([ONE, ONE, ONE, ZERO]))],
463 [(1, StorageMapDelta::default())],
464 );
465 assert!(delta.validate().is_err());
466
467 let bytes = delta.to_bytes();
468 assert!(AccountStorageDelta::read_from_bytes(&bytes).is_err());
469
470 let delta = AccountStorageDelta::from_iters(
472 [1, 3],
473 [(2, Word::from([ONE, ONE, ONE, ONE])), (5, Word::from([ONE, ONE, ONE, ZERO]))],
474 [(2, StorageMapDelta::default())],
475 );
476 assert!(delta.validate().is_err());
477
478 let bytes = delta.to_bytes();
479 assert!(AccountStorageDelta::read_from_bytes(&bytes).is_err());
480 }
481
482 #[test]
483 fn test_is_empty() {
484 let storage_delta = AccountStorageDelta::new();
485 assert!(storage_delta.is_empty());
486
487 let storage_delta = AccountStorageDelta::from_iters([1], [], []);
488 assert!(!storage_delta.is_empty());
489
490 let storage_delta =
491 AccountStorageDelta::from_iters([], [(2, Word::from([ONE, ONE, ONE, ONE]))], []);
492 assert!(!storage_delta.is_empty());
493
494 let storage_delta =
495 AccountStorageDelta::from_iters([], [], [(3, StorageMapDelta::default())]);
496 assert!(!storage_delta.is_empty());
497 }
498
499 #[test]
500 fn test_serde_account_storage_delta() {
501 let storage_delta = AccountStorageDelta::new();
502 let serialized = storage_delta.to_bytes();
503 let deserialized = AccountStorageDelta::read_from_bytes(&serialized).unwrap();
504 assert_eq!(deserialized, storage_delta);
505
506 let storage_delta = AccountStorageDelta::from_iters([1], [], []);
507 let serialized = storage_delta.to_bytes();
508 let deserialized = AccountStorageDelta::read_from_bytes(&serialized).unwrap();
509 assert_eq!(deserialized, storage_delta);
510
511 let storage_delta =
512 AccountStorageDelta::from_iters([], [(2, Word::from([ONE, ONE, ONE, ONE]))], []);
513 let serialized = storage_delta.to_bytes();
514 let deserialized = AccountStorageDelta::read_from_bytes(&serialized).unwrap();
515 assert_eq!(deserialized, storage_delta);
516
517 let storage_delta =
518 AccountStorageDelta::from_iters([], [], [(3, StorageMapDelta::default())]);
519 let serialized = storage_delta.to_bytes();
520 let deserialized = AccountStorageDelta::read_from_bytes(&serialized).unwrap();
521 assert_eq!(deserialized, storage_delta);
522 }
523
524 #[test]
525 fn test_serde_storage_map_delta() {
526 let storage_map_delta = StorageMapDelta::default();
527 let serialized = storage_map_delta.to_bytes();
528 let deserialized = StorageMapDelta::read_from_bytes(&serialized).unwrap();
529 assert_eq!(deserialized, storage_map_delta);
530
531 let storage_map_delta = StorageMapDelta::from_iters([Word::from([ONE, ONE, ONE, ONE])], []);
532 let serialized = storage_map_delta.to_bytes();
533 let deserialized = StorageMapDelta::read_from_bytes(&serialized).unwrap();
534 assert_eq!(deserialized, storage_map_delta);
535
536 let storage_map_delta =
537 StorageMapDelta::from_iters([], [(Word::empty(), Word::from([ONE, ONE, ONE, ONE]))]);
538 let serialized = storage_map_delta.to_bytes();
539 let deserialized = StorageMapDelta::read_from_bytes(&serialized).unwrap();
540 assert_eq!(deserialized, storage_map_delta);
541 }
542
543 #[rstest::rstest]
544 #[case::some_some(Some(1), Some(2), Some(2))]
545 #[case::none_some(None, Some(2), Some(2))]
546 #[case::some_none(Some(1), None, None)]
547 #[test]
548 fn merge_items(
549 #[case] x: Option<u32>,
550 #[case] y: Option<u32>,
551 #[case] expected: Option<u32>,
552 ) -> anyhow::Result<()> {
553 fn create_delta(item: Option<u32>) -> anyhow::Result<AccountStorageDelta> {
555 const SLOT: u8 = 123;
556 let item = item.map(|x| (SLOT, Word::from([x, 0, 0, 0])));
557
558 AccountStorageDeltaBuilder::new()
559 .add_cleared_items(item.is_none().then_some(SLOT))
560 .add_updated_values(item)
561 .build()
562 .context("failed to build storage delta")
563 }
564
565 let mut delta_x = create_delta(x)?;
566 let delta_y = create_delta(y)?;
567 let expected = create_delta(expected)?;
568
569 delta_x.merge(delta_y).context("failed to merge deltas")?;
570
571 assert_eq!(delta_x, expected);
572
573 Ok(())
574 }
575
576 #[rstest::rstest]
577 #[case::some_some(Some(1), Some(2), Some(2))]
578 #[case::none_some(None, Some(2), Some(2))]
579 #[case::some_none(Some(1), None, None)]
580 #[test]
581 fn merge_maps(#[case] x: Option<u32>, #[case] y: Option<u32>, #[case] expected: Option<u32>) {
582 fn create_delta(value: Option<u32>) -> StorageMapDelta {
583 let key = Word::from([10u32, 0, 0, 0]);
584 match value {
585 Some(value) => {
586 StorageMapDelta::from_iters([], [(key, Word::from([value, 0, 0, 0]))])
587 },
588 None => StorageMapDelta::from_iters([key], []),
589 }
590 }
591
592 let mut delta_x = create_delta(x);
593 let delta_y = create_delta(y);
594 let expected = create_delta(expected);
595
596 delta_x.merge(delta_y);
597
598 assert_eq!(delta_x, expected);
599 }
600}