snarkvm_ledger_store/helpers/traits/nested_map.rs
1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM library.
3
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at:
7
8// http://www.apache.org/licenses/LICENSE-2.0
9
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15
16use console::network::prelude::{Deserialize, Result, Serialize};
17
18use core::hash::Hash;
19use std::borrow::Cow;
20
21/// A trait representing 'nested map'-like storage operations with read-write capabilities.
22pub trait NestedMap<
23 'a,
24 M: 'a + Copy + Clone + PartialEq + Eq + Hash + Serialize + Deserialize<'a> + Send + Sync,
25 K: 'a + Clone + PartialEq + Eq + Serialize + Deserialize<'a> + Send + Sync,
26 V: 'a + Clone + Serialize + Deserialize<'a> + Send + Sync,
27>: Clone + NestedMapRead<'a, M, K, V> + Send + Sync
28{
29 ///
30 /// Inserts the given key-value pair.
31 ///
32 fn insert(&self, map: M, key: K, value: V) -> Result<()>;
33
34 ///
35 /// Removes the given map.
36 ///
37 fn remove_map(&self, map: &M) -> Result<()>;
38
39 ///
40 /// Removes the key-value pair for the given map and key.
41 ///
42 fn remove_key(&self, map: &M, key: &K) -> Result<()>;
43
44 ///
45 /// Begins an atomic operation. Any further calls to `insert` and `remove` will be queued
46 /// without an actual write taking place until `finish_atomic` is called.
47 ///
48 fn start_atomic(&self);
49
50 ///
51 /// Checks whether an atomic operation is currently in progress. This can be done to ensure
52 /// that lower-level operations don't start or finish their individual atomic write batch
53 /// if they are already part of a larger one.
54 ///
55 fn is_atomic_in_progress(&self) -> bool;
56
57 ///
58 /// Saves the current list of pending operations, so that if `atomic_rewind` is called,
59 /// we roll back all future operations, and return to the start of this checkpoint.
60 ///
61 fn atomic_checkpoint(&self);
62
63 ///
64 /// Removes the latest atomic checkpoint.
65 ///
66 fn clear_latest_checkpoint(&self);
67
68 ///
69 /// Removes all pending operations to the last `atomic_checkpoint`
70 /// (or to `start_atomic` if no checkpoints have been created).
71 ///
72 fn atomic_rewind(&self);
73
74 ///
75 /// Aborts the current atomic operation.
76 ///
77 fn abort_atomic(&self);
78
79 ///
80 /// Finishes an atomic operation, performing all the queued writes.
81 ///
82 fn finish_atomic(&self) -> Result<()>;
83}
84
85/// A trait representing 'nested map'-like storage operations with read-only capabilities.
86pub trait NestedMapRead<
87 'a,
88 M: 'a + Copy + Clone + PartialEq + Eq + Hash + Serialize + Deserialize<'a> + Sync,
89 K: 'a + Clone + PartialEq + Eq + Serialize + Deserialize<'a> + Sync,
90 V: 'a + Clone + Serialize + Deserialize<'a> + Sync,
91>
92{
93 type PendingIterator: Iterator<Item = (Cow<'a, M>, Option<Cow<'a, K>>, Option<Cow<'a, V>>)>;
94 type Iterator: Iterator<Item = (Cow<'a, M>, Cow<'a, K>, Cow<'a, V>)>;
95 type Keys: Iterator<Item = (Cow<'a, M>, Cow<'a, K>)>;
96 type Values: Iterator<Item = Cow<'a, V>>;
97
98 ///
99 /// Returns the number of confirmed entries in the map.
100 ///
101 fn len_map_confirmed(&self, map: &M) -> Result<usize>;
102
103 ///
104 /// Checks whether there are any confirmed entries in the map.
105 ///
106 fn is_empty_map_confirmed(&self, map: &M) -> Result<bool> {
107 Ok(self.len_map_confirmed(map)? == 0)
108 }
109
110 ///
111 /// Returns `true` if the given key exists in the map.
112 ///
113 fn contains_key_confirmed(&self, map: &M, key: &K) -> Result<bool>;
114
115 ///
116 /// Returns `true` if the given key exists in the map.
117 /// This method first checks the atomic batch, and if it does not exist, then checks the confirmed.
118 ///
119 fn contains_key_speculative(&self, map: &M, key: &K) -> Result<bool>;
120
121 ///
122 /// Returns the confirmed key-value pairs for the given map, if it exists.
123 ///
124 fn get_map_confirmed(&'a self, map: &M) -> Result<Vec<(K, V)>>;
125
126 ///
127 /// Returns the speculative key-value pairs for the given map, if it exists.
128 ///
129 fn get_map_speculative(&'a self, map: &M) -> Result<Vec<(K, V)>>;
130
131 ///
132 /// Returns the value for the given key from the map, if it exists.
133 ///
134 fn get_value_confirmed(&'a self, map: &M, key: &K) -> Result<Option<Cow<'a, V>>>;
135
136 ///
137 /// Returns the current value for the given key if it is scheduled
138 /// to be inserted as part of an atomic batch.
139 ///
140 /// If the key does not exist, returns `None`.
141 /// If the key is removed in the batch, returns `Some(None)`.
142 /// If the key is inserted in the batch, returns `Some(Some(value))`.
143 ///
144 fn get_value_pending(&self, map: &M, key: &K) -> Option<Option<V>>;
145
146 ///
147 /// Returns the value for the given key from the atomic batch first, if it exists,
148 /// or return from the map, otherwise.
149 ///
150 fn get_value_speculative(&'a self, map: &M, key: &K) -> Result<Option<Cow<'a, V>>> {
151 // Return the atomic batch value, if it exists, or the map value, otherwise.
152 match self.get_value_pending(map, key) {
153 Some(Some(value)) => Ok(Some(Cow::Owned(value))),
154 Some(None) => Ok(None),
155 None => Ok(self.get_value_confirmed(map, key)?),
156 }
157 }
158
159 ///
160 /// Returns an iterator visiting each map-key-value pair in the atomic batch.
161 ///
162 fn iter_pending(&'a self) -> Self::PendingIterator;
163
164 ///
165 /// Returns an iterator visiting each confirmed map-key-value pair.
166 ///
167 fn iter_confirmed(&'a self) -> Self::Iterator;
168
169 ///
170 /// Returns an iterator over each confirmed key.
171 ///
172 fn keys_confirmed(&'a self) -> Self::Keys;
173
174 ///
175 /// Returns an iterator over each confirmed value.
176 ///
177 fn values_confirmed(&'a self) -> Self::Values;
178}