1use crate::blockchain::{Error, Result};
10use codec::{Decode, Encode};
11use std::{cmp::Reverse, collections::BTreeMap};
12use subsoil::database::{Database, Transaction};
13use subsoil::runtime::traits::AtLeast32Bit;
14
15type DbHash = subsoil::core::H256;
16
17#[derive(Debug, Clone, PartialEq, Eq)]
18struct LeafSetItem<H, N> {
19 hash: H,
20 number: Reverse<N>,
21}
22
23pub struct ImportOutcome<H, N> {
25 inserted: LeafSetItem<H, N>,
26 removed: Option<H>,
27}
28
29pub struct RemoveOutcome<H, N> {
31 inserted: Option<H>,
32 removed: LeafSetItem<H, N>,
33}
34
35pub struct FinalizationOutcome<I, H, N>
37where
38 I: Iterator<Item = (N, H)>,
39{
40 removed: I,
41}
42
43impl<I, H: Ord, N: Ord> FinalizationOutcome<I, H, N>
44where
45 I: Iterator<Item = (N, H)>,
46{
47 pub fn new(new_displaced: I) -> Self {
49 FinalizationOutcome { removed: new_displaced }
50 }
51}
52
53#[derive(Debug, Clone, PartialEq, Eq)]
57pub struct LeafSet<H, N> {
58 storage: BTreeMap<Reverse<N>, Vec<H>>,
59}
60
61impl<H, N> LeafSet<H, N>
62where
63 H: Clone + PartialEq + Decode + Encode,
64 N: std::fmt::Debug + Copy + AtLeast32Bit + Decode + Encode,
65{
66 pub fn new() -> Self {
68 Self { storage: BTreeMap::new() }
69 }
70
71 pub fn read_from_db(db: &dyn Database<DbHash>, column: u32, prefix: &[u8]) -> Result<Self> {
73 let mut storage = BTreeMap::new();
74
75 match db.get(column, prefix) {
76 Some(leaves) => {
77 let vals: Vec<_> = match Decode::decode(&mut leaves.as_ref()) {
78 Ok(vals) => vals,
79 Err(_) => return Err(Error::Backend("Error decoding leaves".into())),
80 };
81 for (number, hashes) in vals.into_iter() {
82 storage.insert(Reverse(number), hashes);
83 }
84 },
85 None => {},
86 }
87 Ok(Self { storage })
88 }
89
90 pub fn import(&mut self, hash: H, number: N, parent_hash: H) -> ImportOutcome<H, N> {
92 let number = Reverse(number);
93
94 let removed = if number.0 != N::zero() {
95 let parent_number = Reverse(number.0 - N::one());
96 self.remove_leaf(&parent_number, &parent_hash).then(|| parent_hash)
97 } else {
98 None
99 };
100
101 self.insert_leaf(number, hash.clone());
102
103 ImportOutcome { inserted: LeafSetItem { hash, number }, removed }
104 }
105
106 pub fn remove(
115 &mut self,
116 hash: H,
117 number: N,
118 parent_hash: Option<H>,
119 ) -> Option<RemoveOutcome<H, N>> {
120 let number = Reverse(number);
121
122 if !self.remove_leaf(&number, &hash) {
123 return None;
124 }
125
126 let inserted = parent_hash.and_then(|parent_hash| {
127 if number.0 != N::zero() {
128 let parent_number = Reverse(number.0 - N::one());
129 self.insert_leaf(parent_number, parent_hash.clone());
130 Some(parent_hash)
131 } else {
132 None
133 }
134 });
135
136 Some(RemoveOutcome { inserted, removed: LeafSetItem { hash, number } })
137 }
138
139 pub fn remove_displaced_leaves<I>(&mut self, displaced_leaves: FinalizationOutcome<I, H, N>)
141 where
142 I: Iterator<Item = (N, H)>,
143 {
144 for (number, hash) in displaced_leaves.removed {
145 self.remove_leaf(&Reverse(number), &hash);
146 }
147 }
148
149 pub fn undo(&mut self) -> Undo<'_, H, N> {
156 Undo { inner: self }
157 }
158
159 pub fn revert(&mut self, best_hash: H, best_number: N) -> impl Iterator<Item = (H, N)> {
164 let items = self
165 .storage
166 .iter()
167 .flat_map(|(number, hashes)| hashes.iter().map(move |h| (h.clone(), number.0)))
168 .collect::<Vec<_>>();
169
170 for (hash, number) in &items {
171 if *number > best_number {
172 assert!(
173 self.remove_leaf(&Reverse(*number), &hash),
174 "item comes from an iterator over storage; qed",
175 );
176 }
177 }
178
179 let best_number_rev = Reverse(best_number);
180 let leaves_contains_best = self
181 .storage
182 .get(&best_number_rev)
183 .map_or(false, |hashes| hashes.contains(&best_hash));
184
185 if !leaves_contains_best {
188 self.insert_leaf(best_number_rev, best_hash.clone());
189 }
190
191 items.into_iter().filter(move |(_, n)| *n > best_number)
192 }
193
194 pub fn hashes(&self) -> Vec<H> {
197 self.storage.iter().flat_map(|(_, hashes)| hashes.iter()).cloned().collect()
198 }
199
200 pub fn count(&self) -> usize {
202 self.storage.values().map(|level| level.len()).sum()
203 }
204
205 pub fn prepare_transaction(
207 &mut self,
208 tx: &mut Transaction<DbHash>,
209 column: u32,
210 prefix: &[u8],
211 ) {
212 let leaves: Vec<_> = self.storage.iter().map(|(n, h)| (n.0, h.clone())).collect();
213 tx.set_from_vec(column, prefix, leaves.encode());
214 }
215
216 pub fn contains(&self, number: N, hash: H) -> bool {
218 self.storage
219 .get(&Reverse(number))
220 .map_or(false, |hashes| hashes.contains(&hash))
221 }
222
223 fn insert_leaf(&mut self, number: Reverse<N>, hash: H) {
224 self.storage.entry(number).or_insert_with(Vec::new).push(hash);
225 }
226
227 fn remove_leaf(&mut self, number: &Reverse<N>, hash: &H) -> bool {
229 let mut empty = false;
230 let removed = self.storage.get_mut(number).map_or(false, |leaves| {
231 let mut found = false;
232 leaves.retain(|h| {
233 if h == hash {
234 found = true;
235 false
236 } else {
237 true
238 }
239 });
240
241 if leaves.is_empty() {
242 empty = true
243 }
244
245 found
246 });
247
248 if removed && empty {
249 self.storage.remove(number);
250 }
251
252 removed
253 }
254
255 pub fn highest_leaf(&self) -> Option<(N, &[H])> {
257 self.storage.iter().next().map(|(k, v)| (k.0, &v[..]))
258 }
259}
260
261pub struct Undo<'a, H: 'a, N: 'a> {
263 inner: &'a mut LeafSet<H, N>,
264}
265
266impl<'a, H: 'a, N: 'a> Undo<'a, H, N>
267where
268 H: Clone + PartialEq + Decode + Encode,
269 N: std::fmt::Debug + Copy + AtLeast32Bit + Decode + Encode,
270{
271 pub fn undo_import(&mut self, outcome: ImportOutcome<H, N>) {
274 if let Some(removed_hash) = outcome.removed {
275 let removed_number = Reverse(outcome.inserted.number.0 - N::one());
276 self.inner.insert_leaf(removed_number, removed_hash);
277 }
278 self.inner.remove_leaf(&outcome.inserted.number, &outcome.inserted.hash);
279 }
280
281 pub fn undo_remove(&mut self, outcome: RemoveOutcome<H, N>) {
284 if let Some(inserted_hash) = outcome.inserted {
285 let inserted_number = Reverse(outcome.removed.number.0 - N::one());
286 self.inner.remove_leaf(&inserted_number, &inserted_hash);
287 }
288 self.inner.insert_leaf(outcome.removed.number, outcome.removed.hash);
289 }
290
291 pub fn undo_finalization<I>(&mut self, outcome: FinalizationOutcome<I, H, N>)
294 where
295 I: Iterator<Item = (N, H)>,
296 {
297 for (number, hash) in outcome.removed {
298 self.inner.storage.entry(Reverse(number)).or_default().push(hash);
299 }
300 }
301}
302
303#[cfg(test)]
304mod tests {
305 use super::*;
306 use std::sync::Arc;
307
308 #[test]
309 fn import_works() {
310 let mut set = LeafSet::new();
311 set.import(0u32, 0u32, 0u32);
312
313 set.import(1_1, 1, 0);
314 set.import(2_1, 2, 1_1);
315 set.import(3_1, 3, 2_1);
316
317 assert_eq!(set.count(), 1);
318 assert!(set.contains(3, 3_1));
319 assert!(!set.contains(2, 2_1));
320 assert!(!set.contains(1, 1_1));
321 assert!(!set.contains(0, 0));
322
323 set.import(2_2, 2, 1_1);
324 set.import(1_2, 1, 0);
325 set.import(2_3, 2, 1_2);
326
327 assert_eq!(set.count(), 3);
328 assert!(set.contains(3, 3_1));
329 assert!(set.contains(2, 2_2));
330 assert!(set.contains(2, 2_3));
331
332 let outcome = set.import(2_4, 2, 1_1);
335 assert_eq!(outcome.inserted.hash, 2_4);
336 assert_eq!(outcome.removed, None);
337 assert_eq!(set.count(), 4);
338 assert!(set.contains(2, 2_4));
339
340 set.undo().undo_import(outcome);
341 assert_eq!(set.count(), 3);
342 assert!(set.contains(3, 3_1));
343 assert!(set.contains(2, 2_2));
344 assert!(set.contains(2, 2_3));
345
346 let outcome = set.import(3_2, 3, 2_3);
347 assert_eq!(outcome.inserted.hash, 3_2);
348 assert_eq!(outcome.removed, Some(2_3));
349 assert_eq!(set.count(), 3);
350 assert!(set.contains(3, 3_2));
351
352 set.undo().undo_import(outcome);
353 assert_eq!(set.count(), 3);
354 assert!(set.contains(3, 3_1));
355 assert!(set.contains(2, 2_2));
356 assert!(set.contains(2, 2_3));
357 }
358
359 #[test]
360 fn removal_works() {
361 let mut set = LeafSet::new();
362 set.import(10_1u32, 10u32, 0u32);
363 set.import(11_1, 11, 10_1);
364 set.import(11_2, 11, 10_1);
365 set.import(12_1, 12, 11_1);
366
367 let outcome = set.remove(12_1, 12, Some(11_1)).unwrap();
368 assert_eq!(outcome.removed.hash, 12_1);
369 assert_eq!(outcome.inserted, Some(11_1));
370 assert_eq!(set.count(), 2);
371 assert!(set.contains(11, 11_1));
372 assert!(set.contains(11, 11_2));
373
374 let outcome = set.remove(11_1, 11, None).unwrap();
375 assert_eq!(outcome.removed.hash, 11_1);
376 assert_eq!(outcome.inserted, None);
377 assert_eq!(set.count(), 1);
378 assert!(set.contains(11, 11_2));
379
380 let outcome = set.remove(11_2, 11, Some(10_1)).unwrap();
381 assert_eq!(outcome.removed.hash, 11_2);
382 assert_eq!(outcome.inserted, Some(10_1));
383 assert_eq!(set.count(), 1);
384 assert!(set.contains(10, 10_1));
385
386 set.undo().undo_remove(outcome);
387 assert_eq!(set.count(), 1);
388 assert!(set.contains(11, 11_2));
389 }
390
391 #[test]
392 fn flush_to_disk() {
393 const PREFIX: &[u8] = b"abcdefg";
394 let db = Arc::new(subsoil::database::MemDb::default());
395
396 let mut set = LeafSet::new();
397 set.import(0u32, 0u32, 0u32);
398
399 set.import(1_1, 1, 0);
400 set.import(2_1, 2, 1_1);
401 set.import(3_1, 3, 2_1);
402
403 let mut tx = Transaction::new();
404
405 set.prepare_transaction(&mut tx, 0, PREFIX);
406 db.commit(tx).unwrap();
407
408 let set2 = LeafSet::read_from_db(&*db, 0, PREFIX).unwrap();
409 assert_eq!(set, set2);
410 }
411
412 #[test]
413 fn two_leaves_same_height_can_be_included() {
414 let mut set = LeafSet::new();
415
416 set.import(1_1u32, 10u32, 0u32);
417 set.import(1_2, 10, 0);
418
419 assert!(set.storage.contains_key(&Reverse(10)));
420 assert!(set.contains(10, 1_1));
421 assert!(set.contains(10, 1_2));
422 assert!(!set.contains(10, 1_3));
423 }
424}