basecoin_store/impls/
growing.rs

1use ics23::CommitmentProof;
2
3use crate::context::{ProvableStore, Store};
4use crate::types::{Height, Path};
5
6/// GrowingStore does not prune any path.
7/// If the path is set to v, the stored value is v
8/// If the path is deleted, the stored value is []
9/// Note: we should not allow empty vec to store as
10/// this would conflict with the deletion representation.
11#[deprecated(
12    since = "TBD",
13    note = "GrowingStore does not implement deletion. Use InMemoryStore which implements deletion of AVL tree nodes."
14)]
15#[derive(Clone, Debug)]
16pub struct GrowingStore<S> {
17    store: S,
18}
19
20impl<S> GrowingStore<S> {
21    pub fn new(store: S) -> Self {
22        Self { store }
23    }
24}
25
26impl<S> Default for GrowingStore<S>
27where
28    S: Default,
29{
30    fn default() -> Self {
31        Self::new(S::default())
32    }
33}
34
35impl<S> Store for GrowingStore<S>
36where
37    S: Store,
38{
39    type Error = S::Error;
40
41    #[inline]
42    fn set(&mut self, path: Path, value: Vec<u8>) -> Result<Option<Vec<u8>>, Self::Error> {
43        if value.is_empty() {
44            panic!("empty vec is not allowed to store")
45        }
46        self.store.set(path, value)
47    }
48
49    #[inline]
50    fn get(&self, height: Height, path: &Path) -> Option<Vec<u8>> {
51        // ignore if path is deleted
52        self.store.get(height, path).filter(|v| !v.is_empty())
53    }
54
55    #[inline]
56    fn delete(&mut self, path: &Path) {
57        // set value to empty vec to denote the path is deleted.
58        self.store.set(path.clone(), vec![]).expect("delete failed");
59    }
60
61    fn commit(&mut self) -> Result<Vec<u8>, Self::Error> {
62        self.store.commit()
63    }
64
65    #[inline]
66    fn apply(&mut self) -> Result<(), Self::Error> {
67        self.store.apply()
68    }
69
70    #[inline]
71    fn reset(&mut self) {
72        self.store.reset()
73    }
74
75    #[inline]
76    fn prune(&mut self, height: u64) -> Result<u64, Self::Error> {
77        self.store.prune(height)
78    }
79
80    #[inline]
81    fn current_height(&self) -> u64 {
82        self.store.current_height()
83    }
84
85    #[inline]
86    fn get_keys(&self, key_prefix: &Path) -> Vec<Path> {
87        self.store
88            .get_keys(key_prefix)
89            .into_iter()
90            // ignore the deleted paths
91            .filter(|k| {
92                self.get(Height::Pending, k)
93                    .filter(|v| !v.is_empty())
94                    .is_some()
95            })
96            .collect()
97    }
98}
99
100impl<S> ProvableStore for GrowingStore<S>
101where
102    S: ProvableStore,
103{
104    #[inline]
105    fn root_hash(&self) -> Vec<u8> {
106        self.store.root_hash()
107    }
108
109    #[inline]
110    fn get_proof(&self, height: Height, key: &Path) -> Option<CommitmentProof> {
111        self.get(height, key)
112            // ignore if path is deleted
113            .filter(|v| !v.is_empty())
114            .and_then(|_| self.store.get_proof(height, key))
115    }
116}
117
118impl<S> GrowingStore<S>
119where
120    S: Store,
121{
122    #[inline]
123    pub fn is_deleted(&self, path: &Path) -> bool {
124        self.get(Height::Pending, path)
125            .filter(|v| v.is_empty())
126            .is_some()
127    }
128
129    #[inline]
130    pub fn deleted_keys(&self, key_prefix: &Path) -> Vec<Path> {
131        self.store
132            .get_keys(key_prefix)
133            .into_iter()
134            .filter(|k| {
135                self.get(Height::Pending, k)
136                    .filter(|v| v.is_empty())
137                    .is_some()
138            })
139            .collect()
140    }
141}