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(crate) trait NodeSubstatesExt {
33 fn into_node_state_updates(self) -> NodeStateUpdates;
34}
35
36impl NodeSubstatesExt for NodeSubstates {
37 fn into_node_state_updates(self) -> NodeStateUpdates {
38 let mut updates = NodeStateUpdates::empty();
39 for (partition_num, substates) in self {
40 for (substate_key, indexed_scrypto_value) in substates {
41 updates.of_partition(partition_num).mut_update_substate(
42 substate_key,
43 DatabaseUpdate::Set(indexed_scrypto_value.unpack().0),
44 );
45 }
46 }
47 updates
48 }
49}
50
51pub enum TrackedSubstateInfo {
52 New,
53 Updated,
54 Unmodified,
55}
56
57pub trait CommitableSubstateStore {
63 fn mark_as_transient(
65 &mut self,
66 node_id: NodeId,
67 partition_num: PartitionNumber,
68 substate_key: SubstateKey,
69 );
70
71 fn create_node<E, F: FnMut(IOAccess) -> Result<(), E>>(
78 &mut self,
79 node_id: NodeId,
80 node_substates: NodeSubstates,
81 on_io_access: &mut F,
82 ) -> Result<(), E>;
83
84 fn get_tracked_substate_info(
85 &mut self,
86 node_id: &NodeId,
87 partition_num: PartitionNumber,
88 substate_key: &SubstateKey,
89 ) -> TrackedSubstateInfo;
90
91 fn read_substate(
92 &mut self,
93 node_id: &NodeId,
94 partition_num: PartitionNumber,
95 substate_key: &SubstateKey,
96 ) -> Option<&IndexedScryptoValue> {
97 self.get_substate(node_id, partition_num, substate_key, &mut |_| -> Result<
98 (),
99 (),
100 > {
101 Ok(())
102 })
103 .unwrap()
104 }
105
106 fn get_substate<E, F: FnMut(IOAccess) -> Result<(), E>>(
107 &mut self,
108 node_id: &NodeId,
109 partition_num: PartitionNumber,
110 substate_key: &SubstateKey,
111 on_io_access: &mut F,
112 ) -> Result<Option<&IndexedScryptoValue>, E>;
113
114 fn set_substate<E, F: FnMut(IOAccess) -> Result<(), E>>(
119 &mut self,
120 node_id: NodeId,
121 partition_num: PartitionNumber,
122 substate_key: SubstateKey,
123 substate_value: IndexedScryptoValue,
124 on_io_access: &mut F,
125 ) -> Result<(), E>;
126
127 fn force_write(
128 &mut self,
129 node_id: &NodeId,
130 partition_num: &PartitionNumber,
131 substate_key: &SubstateKey,
132 );
133
134 fn remove_substate<E, F: FnMut(IOAccess) -> Result<(), E>>(
142 &mut self,
143 node_id: &NodeId,
144 partition_num: PartitionNumber,
145 substate_key: &SubstateKey,
146 on_io_access: &mut F,
147 ) -> Result<Option<IndexedScryptoValue>, E>;
148
149 fn scan_keys<K: SubstateKeyContent, E, F: FnMut(IOAccess) -> Result<(), E>>(
158 &mut self,
159 node_id: &NodeId,
160 partition_num: PartitionNumber,
161 count: u32,
162 on_io_access: &mut F,
163 ) -> Result<Vec<SubstateKey>, E>;
164
165 fn drain_substates<K: SubstateKeyContent, E, F: FnMut(IOAccess) -> Result<(), E>>(
174 &mut self,
175 node_id: &NodeId,
176 partition_num: PartitionNumber,
177 count: u32,
178 on_io_access: &mut F,
179 ) -> Result<Vec<(SubstateKey, IndexedScryptoValue)>, E>;
180
181 fn scan_sorted_substates<E, F: FnMut(IOAccess) -> Result<(), E>>(
183 &mut self,
184 node_id: &NodeId,
185 partition_num: PartitionNumber,
186 count: u32,
187 on_io_access: &mut F,
188 ) -> Result<Vec<(SortedKey, IndexedScryptoValue)>, E>;
189
190 fn delete_partition(&mut self, node_id: &NodeId, partition_num: PartitionNumber);
192
193 fn get_commit_info(&mut self) -> StoreCommitInfo;
195}
196
197#[derive(Debug, Clone, Copy)]
198pub struct CanonicalPartition {
199 pub node_id: NodeId,
200 pub partition_number: PartitionNumber,
201}
202
203#[derive(Debug, Clone, ScryptoSbor, PartialEq, Eq)]
204pub struct CanonicalSubstateKey {
205 pub node_id: NodeId,
206 pub partition_number: PartitionNumber,
207 pub substate_key: SubstateKey, }
209
210impl CanonicalSubstateKey {
211 pub fn of(partition: CanonicalPartition, substate_key: SubstateKey) -> Self {
212 Self {
213 node_id: partition.node_id,
214 partition_number: partition.partition_number,
215 substate_key,
216 }
217 }
218}
219
220impl CanonicalSubstateKey {
221 #[allow(clippy::len_without_is_empty)]
222 pub fn len(&self) -> usize {
223 self.node_id.as_bytes().len()
224 + 1
225 + match &self.substate_key {
226 SubstateKey::Field(_) => 1,
227 SubstateKey::Map(k) => k.len(),
228 SubstateKey::Sorted(k) => 2 + k.1.len(),
229 }
230 }
231}
232
233#[derive(Debug, Clone, ScryptoSbor, PartialEq, Eq)]
234pub enum IOAccess {
235 ReadFromDb(CanonicalSubstateKey, usize),
237 ReadFromDbNotFound(CanonicalSubstateKey),
239
240 TrackSubstateUpdated {
242 canonical_substate_key: CanonicalSubstateKey,
244 old_size: Option<usize>,
247 new_size: Option<usize>,
249 },
250
251 HeapSubstateUpdated {
253 canonical_substate_key: CanonicalSubstateKey,
255 old_size: Option<usize>,
258 new_size: Option<usize>,
260 },
261}
262
263impl IOAccess {
264 pub fn node_id(&self) -> NodeId {
265 match self {
266 IOAccess::ReadFromDb(key, _)
267 | IOAccess::ReadFromDbNotFound(key)
268 | IOAccess::TrackSubstateUpdated {
269 canonical_substate_key: key,
270 ..
271 }
272 | IOAccess::HeapSubstateUpdated {
273 canonical_substate_key: key,
274 ..
275 } => key.node_id,
276 }
277 }
278}
279
280pub type StoreCommitInfo = Vec<StoreCommit>;
281
282#[derive(Debug, Clone)]
283pub enum StoreCommit {
284 Insert {
285 canonical_substate_key: CanonicalSubstateKey,
286 size: usize,
287 },
288 Update {
289 canonical_substate_key: CanonicalSubstateKey,
290 size: usize,
291 old_size: usize,
292 },
293 Delete {
294 canonical_substate_key: CanonicalSubstateKey,
295 old_size: usize,
296 },
297}
298
299impl StoreCommit {
300 pub fn node_id(&self) -> NodeId {
301 match self {
302 StoreCommit::Insert {
303 canonical_substate_key,
304 ..
305 }
306 | StoreCommit::Update {
307 canonical_substate_key,
308 ..
309 }
310 | StoreCommit::Delete {
311 canonical_substate_key,
312 ..
313 } => canonical_substate_key.node_id,
314 }
315 }
316
317 pub fn len_increase(&self) -> usize {
318 match self {
319 StoreCommit::Insert {
320 canonical_substate_key,
321 size,
322 ..
323 } => canonical_substate_key.len() + *size,
324 StoreCommit::Update { size, old_size, .. } => (*size).saturating_sub(*old_size),
325 StoreCommit::Delete { .. } => 0, }
327 }
328}