ink_storage/lazy/
vec.rs

1// Copyright (C) Use Ink (UK) Ltd.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15//! A simple storage vector implementation built on top of [Mapping].
16//!
17//! # Note
18//!
19//! This vector doesn't actually "own" any data.
20//! Instead it is just a simple wrapper around the contract storage facilities.
21
22use core::cell::Cell;
23use ink_primitives::Key;
24use ink_storage_traits::{
25    AutoKey,
26    Packed,
27    Storable,
28    StorableHint,
29    StorageKey,
30};
31use scale::EncodeLike;
32
33use crate::{
34    Lazy,
35    Mapping,
36};
37
38/// A vector of values (elements) directly on contract storage.
39///
40/// # Important
41///
42/// [StorageVec] requires its own pre-defined storage key where to store values. By
43/// default, the is automatically calculated using [`AutoKey`](crate::traits::AutoKey)
44/// during compilation. However, anyone can specify a storage key using
45/// [`ManualKey`](crate::traits::ManualKey). Specifying the storage key can be helpful for
46/// upgradeable contracts or you want to be resistant to future changes of storage key
47/// calculation strategy.
48///
49/// # Differences between `ink::prelude::vec::Vec` and [StorageVec]
50///
51/// Any `Vec<T>` will exhibit [Packed] storage layout; where
52/// [StorageVec] stores each value under it's own storage key.
53///
54/// Hence, any read or write from or to a `Vec` on storage will load
55/// or store _all_ of its elements.
56///
57/// This can be undesirable:
58/// - The cost of reading or writing a _single_ element grows linearly corresponding to
59///   the number of elements in the vector (its length).
60/// - Additionally, the maximum capacity of the _whole_ vector is limited by
61///   [`pallet-revive's` storage limit for a single cell][pallet-revive-limits] (currently
62///   `416 bytes`).
63/// - Lastly, the maximum capacity of the _whole_ vector is also limited by the size of
64///   [ink!'s static buffer][static-buffer] used during ABI encoding and decoding (current
65///   default is `16 KiB`).
66///
67/// [StorageVec] on the other hand allows to access each element individually.
68/// Thus, it can theoretically grow to infinite size.
69/// However, we currently limit the length at 2 ^ 32 elements. In practice,
70/// even if the vector elements are single bytes, it'll allow to store
71/// more than 4 GB data in blockchain storage.
72///
73/// [pallet-revive-limits]: https://docs.polkadot.com/polkadot-protocol/smart-contract-basics/evm-vs-polkavm/#current-memory-limits
74/// [static-buffer]: https://github.com/use-ink/ink/blob/master/ARCHITECTURE.md#communication-with-the-pallet
75///
76/// # Caveats
77///
78/// Iterators are not provided. [StorageVec] is expected to be used to
79/// store a lot of elements, where iterating through the elements would be
80/// rather inefficient (naturally, it is still possible to manually
81/// iterate over the elements using a loop).
82///
83/// For the same reason, operations which would require re-ordering
84/// stored elements are not supported. Examples include inserting and
85/// deleting elements at arbitrary positions or sorting elements.
86///
87/// The decision whether to use `Vec<T>` or [StorageVec] can be seen as an
88/// optimization problem with several factors:
89/// * How large you expect the vector to grow
90/// * The size of individual elements being stored
91/// * How frequently reads, writes and iterations happen
92///
93/// For example, if a vector is expected to stay small but is frequently
94/// iterated over. Choosing a `Vec<T>` instead of [StorageVec] will be
95/// preferred as individual storage reads are much more expensive as
96/// opposed to retrieving and decoding the whole collection with a single
97/// storage read.
98///
99/// # Storage Layout
100///
101/// At given [StorageKey] `K`, the length of the [StorageVec] is held.
102/// Each element `E` is then stored under a combination of the [StorageVec]
103/// key `K` and the elements index.
104///
105/// Given [StorageVec] under key `K`, the storage key `E` of the `N`th
106/// element is calculated as follows:
107///
108/// `E = scale::Encode((K, N))`
109#[cfg_attr(feature = "std", derive(scale_info::TypeInfo))]
110pub struct StorageVec<V: Packed, KeyType: StorageKey = AutoKey> {
111    /// The number of elements stored on-chain.
112    ///
113    /// # Note
114    ///
115    /// Because of caching, never operate on this field directly!
116    /// Always use `fn get_len()` an `fn set_len()` instead.
117    len: Lazy<u32, KeyType>,
118    /// The length only changes upon pushing to or popping from the vec.
119    /// Hence we can cache it to prevent unnecessary reads from storage.
120    ///
121    /// # Note
122    ///
123    /// Because of caching, never operate on this field directly!
124    /// Always use `fn get_len()` an `fn set_len()` instead.
125    #[cfg_attr(feature = "std", codec(skip))]
126    len_cached: CachedLen,
127    /// We use a [Mapping] to store all elements of the vector.
128    /// Each element is living in storage under `&(KeyType::KEY, index)`.
129    /// Because [StorageVec] has a [StorageKey] parameter under which the
130    /// length and element are stored, it won't collide with the other
131    /// storage fields (unless contract authors purposefully craft such a
132    /// storage layout).
133    elements: Mapping<u32, V, KeyType>,
134}
135
136#[derive(Debug)]
137struct CachedLen(Cell<Option<u32>>);
138
139impl<V, KeyType> Default for StorageVec<V, KeyType>
140where
141    V: Packed,
142    KeyType: StorageKey,
143{
144    fn default() -> Self {
145        Self::new()
146    }
147}
148
149impl<V, KeyType> Storable for StorageVec<V, KeyType>
150where
151    V: Packed,
152    KeyType: StorageKey,
153{
154    #[inline]
155    fn encode<T: scale::Output + ?Sized>(&self, _dest: &mut T) {}
156
157    #[inline]
158    fn decode<I: scale::Input>(_input: &mut I) -> Result<Self, scale::Error> {
159        Ok(Default::default())
160    }
161
162    #[inline]
163    fn encoded_size(&self) -> usize {
164        0
165    }
166}
167
168impl<V, Key, InnerKey> StorableHint<Key> for StorageVec<V, InnerKey>
169where
170    V: Packed,
171    Key: StorageKey,
172    InnerKey: StorageKey,
173{
174    type Type = StorageVec<V, Key>;
175    type PreferredKey = InnerKey;
176}
177
178impl<V, KeyType> StorageKey for StorageVec<V, KeyType>
179where
180    V: Packed,
181    KeyType: StorageKey,
182{
183    const KEY: Key = KeyType::KEY;
184}
185
186#[cfg(feature = "std")]
187const _: () = {
188    use crate::traits::StorageLayout;
189    use ink_metadata::layout::{
190        Layout,
191        LayoutKey,
192        RootLayout,
193    };
194
195    impl<V, KeyType> StorageLayout for StorageVec<V, KeyType>
196    where
197        V: Packed + StorageLayout + scale_info::TypeInfo + 'static,
198        KeyType: StorageKey + scale_info::TypeInfo + 'static,
199    {
200        fn layout(_: &Key) -> Layout {
201            Layout::Root(RootLayout::new(
202                LayoutKey::from(&KeyType::KEY),
203                <V as StorageLayout>::layout(&KeyType::KEY),
204                scale_info::meta_type::<Self>(),
205            ))
206        }
207    }
208};
209
210impl<V, KeyType> StorageVec<V, KeyType>
211where
212    V: Packed,
213    KeyType: StorageKey,
214{
215    /// Creates a new empty `StorageVec`.
216    pub const fn new() -> Self {
217        Self {
218            len: Lazy::new(),
219            len_cached: CachedLen(Cell::new(None)),
220            elements: Mapping::new(),
221        }
222    }
223
224    /// Returns the number of elements in the vector, also referred to as its length.
225    ///
226    /// The length is cached; subsequent calls (without writing to the vector) won't
227    /// trigger additional storage reads.
228    #[inline]
229    pub fn len(&self) -> u32 {
230        let cached_len = self.len_cached.0.get();
231
232        debug_assert!(cached_len.is_none() || self.len.get() == cached_len);
233
234        cached_len.unwrap_or_else(|| {
235            let value = self.len.get();
236            self.len_cached.0.set(value);
237            value.unwrap_or(u32::MIN)
238        })
239    }
240
241    /// Overwrite the length. Writes directly to contract storage.
242    fn set_len(&mut self, new_len: u32) {
243        self.len.set(&new_len);
244        self.len_cached.0.set(Some(new_len));
245    }
246
247    /// Returns `true` if the vector contains no elements.
248    pub fn is_empty(&self) -> bool {
249        self.len() == 0
250    }
251
252    /// Appends an element to the back of the vector.
253    ///
254    /// # Panics
255    ///
256    /// * If the vector is at capacity (max. of 2 ^ 32 elements).
257    /// * If the value overgrows the static buffer size.
258    /// * If there was already a value at the current index.
259    pub fn push<T>(&mut self, value: &T)
260    where
261        T: Storable + scale::EncodeLike<V>,
262    {
263        let slot = self.len();
264        self.set_len(slot.checked_add(1).expect("unable to checked_add"));
265
266        assert!(self.elements.insert(slot, value).is_none());
267    }
268
269    /// Try to append an element to the back of the vector.
270    ///
271    /// Returns:
272    ///
273    /// * `Ok(())` if the value was inserted successfully
274    /// * `Err(_)` if the encoded value exceeds the static buffer size.
275    pub fn try_push<T>(&mut self, value: &T) -> Result<(), ink_env::Error>
276    where
277        T: Storable + scale::EncodeLike<V>,
278    {
279        let slot = self.len();
280        self.set_len(slot.checked_add(1).unwrap());
281
282        assert!(self.elements.try_insert(slot, value)?.is_none());
283
284        Ok(())
285    }
286
287    /// Clears the last element from the storage and returns it.
288    /// Shrinks the length of the vector by one.
289    //
290    /// Returns `None` if the vector is empty or if the last
291    /// element was already cleared from storage.
292    ///
293    /// # Panics
294    ///
295    /// * If the value overgrows the static buffer size.
296    pub fn pop(&mut self) -> Option<V> {
297        if self.is_empty() {
298            return None;
299        }
300
301        let slot = self.len().checked_sub(1).unwrap();
302        self.set_len(slot);
303
304        self.elements.take(slot)
305    }
306
307    /// Try to clear and return the last element from storage.
308    /// Shrinks the length of the vector by one.
309    //
310    /// Returns `None` if the vector is empty.
311    ///
312    /// Returns
313    ///
314    /// `Some(Ok(_))` containing the value if it existed and was decoded successfully.
315    /// `Some(Err(_))` if the value existed but its length exceeds the static buffer size.
316    /// `None` if the vector is empty.
317    pub fn try_pop(&mut self) -> Option<Result<V, ink_env::Error>> {
318        if self.is_empty() {
319            return None;
320        }
321
322        let slot = self.len().checked_sub(1).expect("unable to checked_sub");
323        self.set_len(slot);
324
325        self.elements.try_take(slot)
326    }
327
328    /// Get a copy of the last element without removing it from storage.
329    ///
330    /// # Panics
331    ///
332    /// * If the value overgrows the static buffer size.
333    pub fn peek(&self) -> Option<V> {
334        if self.is_empty() {
335            return None;
336        }
337
338        let slot = self.len().checked_sub(1).expect("unable to checked_sub");
339        self.elements.get(slot)
340    }
341
342    /// Try to get a copy of the last element without removing it from storage.
343    ///
344    /// Returns:
345    ///
346    /// `Some(Ok(_))` containing the value if it existed and was decoded successfully.
347    /// `Some(Err(_))` if the value existed but its length exceeds the static buffer size.
348    /// `None` if the vector is empty.
349    pub fn try_peek(&self) -> Option<Result<V, ink_env::Error>> {
350        if self.is_empty() {
351            return None;
352        }
353
354        let slot = self.len().checked_sub(1).expect("unable to checked_sub");
355        self.elements.try_get(slot)
356    }
357
358    /// Access an element at given `index`.
359    ///
360    /// Returns `None` if there was no value at the `index`.
361    ///
362    /// # Panics
363    ///
364    /// * If encoding the element exceeds the static buffer size.
365    pub fn get(&self, index: u32) -> Option<V> {
366        self.elements.get(index)
367    }
368
369    /// Try to access an element at given `index`.
370    ///
371    /// Returns:
372    ///
373    /// * `Some(Ok(_))` containing the value if it existed and was decoded successfully.
374    /// * `Some(Err(_))` if the value existed but its length exceeds the static buffer
375    ///   size.
376    /// * `None` if there was no value at `index`.
377    pub fn try_get(&self, index: u32) -> Option<ink_env::Result<V>> {
378        self.elements.try_get(index)
379    }
380
381    /// Set the `value` at given `index`.
382    ///
383    /// # Panics
384    ///
385    /// * If the index is out of bounds.
386    /// * If decoding the element exceeds the static buffer size.
387    pub fn set<T>(&mut self, index: u32, value: &T) -> Option<u32>
388    where
389        T: Storable + EncodeLike<V>,
390    {
391        assert!(index < self.len());
392
393        self.elements.insert(index, value)
394    }
395
396    /// Try to set the `value` at given `index`.
397    ///
398    /// Returns:
399    ///
400    /// * `Ok(Some(_))` if the value was inserted successfully, containing the size in
401    ///   bytes of the pre-existing value at the specified key if any.
402    /// * `Ok(None)` if the insert was successful but there was no pre-existing value.
403    /// * Err([`ink_env::Error::BufferTooSmall`]) if the encoded value exceeds the static
404    ///   buffer size
405    /// * Err([`ink_env::Error::ReturnError`]\([`ink_env::ReturnErrorCode::KeyNotFound`]))
406    ///   if the `index` is out of bounds.
407    ///
408    /// # Panics
409    ///
410    /// Panics if `index` exceeds the length of the vector.
411    pub fn try_set<T>(
412        &mut self,
413        index: u32,
414        value: &T,
415    ) -> Result<Option<u32>, ink_env::Error>
416    where
417        T: Storable + EncodeLike<V>,
418    {
419        if index >= self.len() {
420            return Err(ink_env::ReturnErrorCode::KeyNotFound.into());
421        }
422
423        self.elements.try_insert(index, value)
424    }
425
426    /// Delete all elements from storage.
427    ///
428    /// # Warning
429    ///
430    /// This iterates through all elements in the vector; complexity is O(n).
431    /// It might not be possible to clear large vectors within a single block!
432    pub fn clear(&mut self) {
433        for i in 0..self.len() {
434            self.elements.remove(i);
435        }
436        self.set_len(0);
437    }
438
439    /// Clears the value of the element at `index`. It doesn't change the length of the
440    /// vector.
441    ///
442    /// # Panics
443    ///
444    /// Panics if `index` exceeds the length of the vector.
445    pub fn clear_at(&mut self, index: u32) {
446        assert!(index < self.len());
447
448        self.elements.remove(index);
449    }
450}
451
452impl<V, KeyType> FromIterator<V> for StorageVec<V, KeyType>
453where
454    V: Packed + EncodeLike<V>,
455    KeyType: StorageKey,
456{
457    fn from_iter<T: IntoIterator<Item = V>>(iter: T) -> Self {
458        let mut result = StorageVec::<V, KeyType>::new();
459
460        for element in iter {
461            result.push(&element);
462        }
463
464        result
465    }
466}
467
468impl<V, KeyType> ::core::fmt::Debug for StorageVec<V, KeyType>
469where
470    V: Packed,
471    KeyType: StorageKey,
472{
473    fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
474        f.debug_struct("StorageVec")
475            .field("key", &KeyType::KEY)
476            .field("len", &self.len)
477            .field("len_cached", &self.len_cached)
478            .finish()
479    }
480}
481
482#[cfg(test)]
483mod tests {
484    use super::*;
485    use crate::traits::ManualKey;
486
487    #[test]
488    fn empty_vec_works_as_expected() {
489        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
490            let mut array: StorageVec<String> = StorageVec::new();
491
492            assert_eq!(array.pop(), None);
493            assert_eq!(array.peek(), None);
494            assert_eq!(array.len(), 0);
495            assert!(array.is_empty());
496
497            Ok(())
498        })
499        .unwrap()
500    }
501
502    #[test]
503    fn push_and_pop_work() {
504        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
505            let mut array: StorageVec<String> = StorageVec::new();
506
507            let value = "test".to_string();
508            array.push(&value);
509            assert_eq!(array.len(), 1);
510            assert_eq!(array.pop(), Some(value));
511
512            Ok(())
513        })
514        .unwrap()
515    }
516
517    #[test]
518    fn storage_keys_are_correct() {
519        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
520            const BASE: u32 = 123;
521            let mut array: StorageVec<u8, ManualKey<BASE>> = StorageVec::new();
522
523            let expected_value = 127;
524            array.push(&expected_value);
525
526            let actual_length = ink_env::get_contract_storage::<_, u32>(&BASE);
527            assert_eq!(actual_length, Ok(Some(1)));
528
529            let actual_value = ink_env::get_contract_storage::<_, u8>(&(BASE, 0u32));
530            assert_eq!(actual_value, Ok(Some(expected_value)));
531
532            Ok(())
533        })
534        .unwrap()
535    }
536
537    #[test]
538    fn push_and_pop_work_for_two_vecs_with_same_manual_key() {
539        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
540            let expected_value = 255;
541
542            let mut array: StorageVec<u8, ManualKey<{ u32::MIN }>> = StorageVec::new();
543            array.push(&expected_value);
544
545            let mut array2: StorageVec<u8, ManualKey<{ u32::MIN }>> = StorageVec::new();
546            assert_eq!(array2.pop(), Some(expected_value));
547
548            Ok(())
549        })
550        .unwrap()
551    }
552
553    #[test]
554    fn set_and_get_work() {
555        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
556            let mut array: StorageVec<String> = StorageVec::new();
557
558            let value = "test".to_string();
559            array.push(&value);
560            assert_eq!(array.get(0), Some(value));
561            assert_eq!(array.len(), 1);
562
563            let replaced_value = "foo".to_string();
564            array.set(0, &replaced_value);
565            assert_eq!(array.get(0), Some(replaced_value));
566
567            Ok(())
568        })
569        .unwrap()
570    }
571
572    #[test]
573    #[should_panic]
574    fn set_panics_on_oob() {
575        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
576            StorageVec::<u8>::new().set(0, &0);
577
578            Ok(())
579        })
580        .unwrap()
581    }
582
583    #[test]
584    fn clear_works() {
585        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
586            let mut array: StorageVec<u128> = (0..1024).collect();
587
588            array.clear();
589
590            assert_eq!(array.len(), 0);
591            assert_eq!(array.pop(), None);
592
593            Ok(())
594        })
595        .unwrap()
596    }
597
598    #[test]
599    fn clear_on_empty_works() {
600        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
601            let mut array: StorageVec<bool> = StorageVec::new();
602
603            array.clear();
604
605            assert_eq!(array.len(), 0);
606            assert_eq!(array.pop(), None);
607
608            Ok(())
609        })
610        .unwrap()
611    }
612
613    #[test]
614    fn clear_at_works() {
615        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
616            let mut array: StorageVec<u64> = (0..1024).collect();
617
618            array.clear_at(0);
619            assert_eq!(array.len(), 1024);
620            assert_eq!(array.get(0), None);
621
622            let last_idx = array.len() - 1;
623            assert_eq!(array.get(last_idx), Some(1023));
624            array.clear_at(last_idx);
625            assert_eq!(array.get(last_idx), None);
626
627            Ok(())
628        })
629        .unwrap()
630    }
631
632    #[test]
633    #[should_panic]
634    fn clear_at_invalid_index_panics() {
635        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
636            StorageVec::<u32>::new().clear_at(0);
637
638            Ok(())
639        })
640        .unwrap()
641    }
642
643    #[test]
644    fn try_get_works() {
645        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
646            let array: StorageVec<u32> = (0..10).collect();
647
648            assert_eq!(array.try_get(0), Some(Ok(0)));
649            assert_eq!(array.try_get(11), None);
650
651            Ok(())
652        })
653        .unwrap()
654    }
655
656    #[test]
657    fn try_set_works() {
658        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
659            let mut array: StorageVec<u32> = (0..10).collect();
660
661            assert_eq!(array.try_set(0, &1), Ok(Some(4)));
662            assert_eq!(
663                array.try_set(10, &1),
664                Err(ink_env::Error::ReturnError(
665                    ink_env::ReturnErrorCode::KeyNotFound
666                ))
667            );
668
669            array.clear_at(0);
670            assert_eq!(array.try_set(0, &1), Ok(None));
671
672            Ok(())
673        })
674        .unwrap()
675    }
676
677    #[test]
678    fn fallible_push_pop_peek_works() {
679        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
680            let mut array: StorageVec<u32> = (0..10).collect();
681
682            assert_eq!(array.try_push(&10), Ok(()));
683            assert_eq!(array.try_pop(), Some(Ok(10)));
684            assert_eq!(array.try_peek(), Some(Ok(9)));
685
686            array.clear();
687            assert_eq!(array.try_pop(), None);
688            assert_eq!(array.try_peek(), None);
689
690            Ok(())
691        })
692        .unwrap()
693    }
694
695    #[test]
696    fn peek_works() {
697        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
698            let mut array = StorageVec::<u32>::new();
699            assert_eq!(array.peek(), None);
700
701            array.push(&0);
702            array.push(&9);
703
704            assert_eq!(array.peek(), Some(9));
705            assert_eq!(array.peek(), Some(9));
706            assert_eq!(array.len(), 2);
707
708            array.clear();
709            assert_eq!(array.peek(), None);
710            assert_eq!(array.len(), 0);
711
712            Ok(())
713        })
714        .unwrap()
715    }
716
717    #[test]
718    fn from_iter_works() {
719        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
720            let array = StorageVec::<u32>::from_iter([u32::MIN, u32::MAX]);
721
722            assert_eq!(array.len(), 2);
723            assert_eq!(array.get(0), Some(u32::MIN));
724            assert_eq!(array.get(1), Some(u32::MAX));
725
726            Ok(())
727        })
728        .unwrap()
729    }
730
731    #[test]
732    #[should_panic(
733        expected = "assertion failed: cached_len.is_none() || self.len.get() == cached_len"
734    )]
735    fn cached_len_works() {
736        ink_env::test::run_test::<ink_env::DefaultEnvironment, _>(|_| {
737            let array = StorageVec::<u32>::from_iter([u32::MIN, u32::MAX]);
738
739            assert_eq!(array.len(), 2);
740
741            // Force overwrite the length
742            Lazy::<u32>::new().set(&u32::MAX);
743
744            // This should fail the debug assert
745            let _ = array.len();
746
747            Ok(())
748        })
749        .unwrap()
750    }
751}