1use crate::errors::RuntimeError;
2use crate::internal_prelude::*;
3use radix_engine_interface::types::*;
4use radix_substate_store_interface::db_key_mapper::SubstateKeyContent;
5
6#[derive(Debug, Clone, PartialEq, Eq)]
7pub enum CallbackError<E, C> {
8 Error(E),
9 CallbackError(C),
10}
11
12impl<E> CallbackError<E, RuntimeError> {
13 pub fn to_runtime_error<F: FnOnce(E) -> RuntimeError>(self, f: F) -> RuntimeError {
14 match self {
15 CallbackError::Error(e) => f(e),
16 CallbackError::CallbackError(c) => c,
17 }
18 }
19}
20
21impl<E, C> CallbackError<E, C> {
22 pub fn map<N, F: FnOnce(E) -> N>(self, f: F) -> CallbackError<N, C> {
23 match self {
24 CallbackError::Error(e) => CallbackError::Error(f(e)),
25 CallbackError::CallbackError(c) => CallbackError::CallbackError(c),
26 }
27 }
28}
29
30pub type NodeSubstates = BTreeMap<PartitionNumber, BTreeMap<SubstateKey, IndexedScryptoValue>>;
31
32pub enum TrackedSubstateInfo {
33 New,
34 Updated,
35 Unmodified,
36}
37
38pub trait CommitableSubstateStore {
44 fn mark_as_transient(
46 &mut self,
47 node_id: NodeId,
48 partition_num: PartitionNumber,
49 substate_key: SubstateKey,
50 );
51
52 fn create_node<E, F: FnMut(IOAccess) -> Result<(), E>>(
59 &mut self,
60 node_id: NodeId,
61 node_substates: NodeSubstates,
62 on_io_access: &mut F,
63 ) -> Result<(), E>;
64
65 fn get_tracked_substate_info(
66 &mut self,
67 node_id: &NodeId,
68 partition_num: PartitionNumber,
69 substate_key: &SubstateKey,
70 ) -> TrackedSubstateInfo;
71
72 fn read_substate(
73 &mut self,
74 node_id: &NodeId,
75 partition_num: PartitionNumber,
76 substate_key: &SubstateKey,
77 ) -> Option<&IndexedScryptoValue> {
78 self.get_substate(node_id, partition_num, substate_key, &mut |_| -> Result<
79 (),
80 (),
81 > {
82 Ok(())
83 })
84 .unwrap()
85 }
86
87 fn get_substate<E, F: FnMut(IOAccess) -> Result<(), E>>(
88 &mut self,
89 node_id: &NodeId,
90 partition_num: PartitionNumber,
91 substate_key: &SubstateKey,
92 on_io_access: &mut F,
93 ) -> Result<Option<&IndexedScryptoValue>, E>;
94
95 fn set_substate<E, F: FnMut(IOAccess) -> Result<(), E>>(
100 &mut self,
101 node_id: NodeId,
102 partition_num: PartitionNumber,
103 substate_key: SubstateKey,
104 substate_value: IndexedScryptoValue,
105 on_io_access: &mut F,
106 ) -> Result<(), E>;
107
108 fn force_write(
109 &mut self,
110 node_id: &NodeId,
111 partition_num: &PartitionNumber,
112 substate_key: &SubstateKey,
113 );
114
115 fn remove_substate<E, F: FnMut(IOAccess) -> Result<(), E>>(
123 &mut self,
124 node_id: &NodeId,
125 partition_num: PartitionNumber,
126 substate_key: &SubstateKey,
127 on_io_access: &mut F,
128 ) -> Result<Option<IndexedScryptoValue>, E>;
129
130 fn scan_keys<K: SubstateKeyContent, E, F: FnMut(IOAccess) -> Result<(), E>>(
139 &mut self,
140 node_id: &NodeId,
141 partition_num: PartitionNumber,
142 count: u32,
143 on_io_access: &mut F,
144 ) -> Result<Vec<SubstateKey>, E>;
145
146 fn drain_substates<K: SubstateKeyContent, E, F: FnMut(IOAccess) -> Result<(), E>>(
155 &mut self,
156 node_id: &NodeId,
157 partition_num: PartitionNumber,
158 count: u32,
159 on_io_access: &mut F,
160 ) -> Result<Vec<(SubstateKey, IndexedScryptoValue)>, E>;
161
162 fn scan_sorted_substates<E, F: FnMut(IOAccess) -> Result<(), E>>(
164 &mut self,
165 node_id: &NodeId,
166 partition_num: PartitionNumber,
167 count: u32,
168 on_io_access: &mut F,
169 ) -> Result<Vec<(SortedKey, IndexedScryptoValue)>, E>;
170
171 fn delete_partition(&mut self, node_id: &NodeId, partition_num: PartitionNumber);
173
174 fn get_commit_info(&mut self) -> StoreCommitInfo;
176}
177
178#[derive(Debug, Clone, Copy)]
179pub struct CanonicalPartition {
180 pub node_id: NodeId,
181 pub partition_number: PartitionNumber,
182}
183
184#[derive(Debug, Clone, ScryptoSbor, PartialEq, Eq)]
185pub struct CanonicalSubstateKey {
186 pub node_id: NodeId,
187 pub partition_number: PartitionNumber,
188 pub substate_key: SubstateKey, }
190
191impl CanonicalSubstateKey {
192 pub fn of(partition: CanonicalPartition, substate_key: SubstateKey) -> Self {
193 Self {
194 node_id: partition.node_id,
195 partition_number: partition.partition_number,
196 substate_key,
197 }
198 }
199}
200
201impl CanonicalSubstateKey {
202 pub fn len(&self) -> usize {
203 self.node_id.as_bytes().len()
204 + 1
205 + match &self.substate_key {
206 SubstateKey::Field(_) => 1,
207 SubstateKey::Map(k) => k.len(),
208 SubstateKey::Sorted(k) => 2 + k.1.len(),
209 }
210 }
211}
212
213#[derive(Debug, Clone, ScryptoSbor, PartialEq, Eq)]
214pub enum IOAccess {
215 ReadFromDb(CanonicalSubstateKey, usize),
217 ReadFromDbNotFound(CanonicalSubstateKey),
219
220 TrackSubstateUpdated {
222 canonical_substate_key: CanonicalSubstateKey,
224 old_size: Option<usize>,
227 new_size: Option<usize>,
229 },
230
231 HeapSubstateUpdated {
233 canonical_substate_key: CanonicalSubstateKey,
235 old_size: Option<usize>,
238 new_size: Option<usize>,
240 },
241}
242
243impl IOAccess {
244 pub fn node_id(&self) -> NodeId {
245 match self {
246 IOAccess::ReadFromDb(key, _)
247 | IOAccess::ReadFromDbNotFound(key)
248 | IOAccess::TrackSubstateUpdated {
249 canonical_substate_key: key,
250 ..
251 }
252 | IOAccess::HeapSubstateUpdated {
253 canonical_substate_key: key,
254 ..
255 } => key.node_id,
256 }
257 }
258}
259
260pub type StoreCommitInfo = Vec<StoreCommit>;
261
262#[derive(Debug, Clone)]
263pub enum StoreCommit {
264 Insert {
265 canonical_substate_key: CanonicalSubstateKey,
266 size: usize,
267 },
268 Update {
269 canonical_substate_key: CanonicalSubstateKey,
270 size: usize,
271 old_size: usize,
272 },
273 Delete {
274 canonical_substate_key: CanonicalSubstateKey,
275 old_size: usize,
276 },
277}
278
279impl StoreCommit {
280 pub fn node_id(&self) -> NodeId {
281 match self {
282 StoreCommit::Insert {
283 canonical_substate_key,
284 ..
285 }
286 | StoreCommit::Update {
287 canonical_substate_key,
288 ..
289 }
290 | StoreCommit::Delete {
291 canonical_substate_key,
292 ..
293 } => canonical_substate_key.node_id,
294 }
295 }
296
297 pub fn len_increase(&self) -> usize {
298 match self {
299 StoreCommit::Insert {
300 canonical_substate_key,
301 size,
302 ..
303 } => canonical_substate_key.len() + *size,
304 StoreCommit::Update { size, old_size, .. } => {
305 if *size > *old_size {
306 *size - *old_size
307 } else {
308 0
309 }
310 }
311 StoreCommit::Delete { .. } => 0, }
313 }
314}