penumbra_sdk_tct/storage/
in_memory.rs1use super::*;
4
5#[derive(Debug, Clone, PartialEq, Eq, Hash, Default, Serialize, Deserialize)]
7pub struct InMemory {
8 sparse: bool,
9 position: StoredPosition,
10 forgotten: Forgotten,
11 hashes: BTreeMap<Position, BTreeMap<u8, Hash>>,
12 commitments: BTreeMap<Position, StateCommitment>,
13}
14
15impl InMemory {
16 pub fn new() -> Self {
18 Self::default()
19 }
20
21 pub fn new_sparse() -> Self {
23 let mut new = Self::new();
24 new.sparse = true;
25 new
26 }
27
28 pub fn position(&self) -> StoredPosition {
30 self.position
31 }
32
33 pub fn forgotten(&self) -> Forgotten {
35 self.forgotten
36 }
37
38 pub fn hashes(&self) -> impl Iterator<Item = (Position, u8, Hash)> + '_ {
40 self.hashes.iter().flat_map(|(position, hashes)| {
41 hashes
42 .iter()
43 .map(move |(height, hash)| (*position, *height, *hash))
44 })
45 }
46
47 pub fn commitments(&self) -> impl Iterator<Item = (Position, StateCommitment)> + '_ {
49 self.commitments
50 .iter()
51 .map(|(position, commitment)| (*position, *commitment))
52 }
53}
54
55#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Error)]
57pub enum Error {
58 #[error("refusing to overwrite existing commitment at position {position:?}")]
60 DuplicateWriteCommitment {
61 position: Position,
63 },
64 #[error("repeated write of hash at position {position:?}, height {height}")]
66 RepeatedWriteHash {
67 position: Position,
69 height: u8,
71 },
72 #[error("hash overwritten with different hash at position {position:?}, height {height}")]
74 OverwrittenHash {
75 position: Position,
77 height: u8,
79 },
80 #[error("recalculable hash marked essential at position {position:?}, height {height}")]
82 EssentialHashHasChildren {
83 position: Position,
85 height: u8,
87 },
88 #[error("set position did not increase from {previous:?} to {new:?}")]
90 PositionDidNotIncrease {
91 previous: StoredPosition,
93 new: StoredPosition,
95 },
96 #[error("set forgotten version did not increase from {previous:?} to {new:?}")]
98 ForgottenDidNotIncrease {
99 previous: Forgotten,
101 new: Forgotten,
103 },
104}
105
106impl Read for InMemory {
107 type Error = Error;
108
109 type HashesIter<'a> =
110 Box<dyn Iterator<Item = Result<(Position, u8, Hash), Self::Error>> + Send + 'a>;
111 type CommitmentsIter<'a> =
112 Box<dyn Iterator<Item = Result<(Position, StateCommitment), Self::Error>> + Send + 'a>;
113
114 fn position(&mut self) -> Result<StoredPosition, Self::Error> {
115 Ok(self.position)
116 }
117
118 fn forgotten(&mut self) -> Result<Forgotten, Self::Error> {
119 Ok(self.forgotten)
120 }
121
122 fn hash(&mut self, position: Position, height: u8) -> Result<Option<Hash>, Self::Error> {
123 Ok(self
124 .hashes
125 .get(&position)
126 .and_then(|h| h.get(&height))
127 .cloned())
128 }
129
130 fn hashes(&mut self) -> Self::HashesIter<'_> {
131 Box::new(InMemory::hashes(self).map(Ok))
132 }
133
134 fn commitment(&mut self, position: Position) -> Result<Option<StateCommitment>, Self::Error> {
135 Ok(self.commitments.get(&position).cloned())
136 }
137
138 fn commitments(&mut self) -> Self::CommitmentsIter<'_> {
139 Box::new(InMemory::commitments(self).map(Ok))
140 }
141}
142
143impl Write for InMemory {
144 fn add_hash(
145 &mut self,
146 position: Position,
147 height: u8,
148 hash: Hash,
149 essential: bool,
150 ) -> Result<(), Self::Error> {
151 if !essential && self.sparse {
152 return Ok(());
154 }
155
156 let column = self.hashes.entry(position).or_default();
157 match column.entry(height) {
159 Entry::Vacant(e) => {
160 e.insert(hash);
161 }
162 Entry::Occupied(e) => {
163 if !essential {
164 return Err(Error::RepeatedWriteHash { position, height });
165 }
166 if *e.into_mut() != hash {
167 return Err(Error::OverwrittenHash { position, height });
168 }
169 }
170 };
171 Ok(())
172 }
173
174 fn add_commitment(
175 &mut self,
176 position: Position,
177 commitment: StateCommitment,
178 ) -> Result<(), Self::Error> {
179 match self.commitments.entry(position) {
181 Entry::Vacant(e) => e.insert(commitment),
182 Entry::Occupied(_) => return Err(Error::DuplicateWriteCommitment { position }),
183 };
184 Ok(())
185 }
186
187 fn delete_range(
188 &mut self,
189 below_height: u8,
190 range: Range<Position>,
191 ) -> Result<(), Self::Error> {
192 let empty_columns: Vec<Position> = self
194 .hashes
195 .range_mut(range.clone())
196 .filter_map(|(&position, column)| {
197 *column = column.split_off(&below_height);
198 if column.is_empty() {
199 Some(position)
200 } else {
201 None
202 }
203 })
204 .collect();
205
206 for position in empty_columns {
208 self.hashes.remove(&position);
209 }
210
211 let commitments_to_delete: Vec<Position> = self
213 .commitments
214 .range(range)
215 .map(|(&position, _)| position)
216 .collect();
217
218 for position in commitments_to_delete {
220 self.commitments.remove(&position);
221 }
222
223 Ok(())
224 }
225
226 fn set_position(&mut self, position: StoredPosition) -> Result<(), Self::Error> {
227 if self.position >= position {
228 return Err(Error::PositionDidNotIncrease {
229 previous: self.position,
230 new: position,
231 });
232 }
233 self.position = position;
234 Ok(())
235 }
236
237 fn set_forgotten(&mut self, forgotten: Forgotten) -> Result<(), Self::Error> {
238 if self.forgotten >= forgotten {
239 return Err(Error::ForgottenDidNotIncrease {
240 previous: self.forgotten,
241 new: forgotten,
242 });
243 }
244 self.forgotten = forgotten;
245 Ok(())
246 }
247}