radix_engine/track/
state_updates.rs

1use crate::internal_prelude::*;
2use radix_rust::rust::{iter::*, mem};
3use radix_substate_store_interface::interface::*;
4
5#[derive(Clone, Debug)]
6pub struct RuntimeSubstate {
7    pub value: IndexedScryptoValue,
8}
9
10impl RuntimeSubstate {
11    pub fn new(value: IndexedScryptoValue) -> Self {
12        Self { value }
13    }
14}
15
16#[derive(Clone, Debug)]
17pub enum ReadOnly {
18    NonExistent,
19    Existent(RuntimeSubstate),
20}
21
22#[derive(Clone, Debug)]
23pub enum Write {
24    Update(RuntimeSubstate),
25    Delete,
26}
27
28impl Write {
29    pub fn into_value(self) -> Option<IndexedScryptoValue> {
30        match self {
31            Write::Update(substate) => Some(substate.value),
32            Write::Delete => None,
33        }
34    }
35}
36
37#[derive(Clone, Debug)]
38pub struct TrackedSubstate {
39    pub substate_key: SubstateKey,
40    pub substate_value: TrackedSubstateValue,
41}
42
43// TODO: Add new virtualized
44#[derive(Clone, Debug)]
45pub enum TrackedSubstateValue {
46    New(RuntimeSubstate),
47    ReadOnly(ReadOnly),
48    ReadExistAndWrite(IndexedScryptoValue, Write),
49    ReadNonExistAndWrite(RuntimeSubstate),
50    WriteOnly(Write),
51    Garbage,
52}
53
54impl TrackedSubstate {
55    pub fn size(&self) -> usize {
56        // `substate_key` is accounted as part of the CanonicalSubstateKey
57        self.substate_value.size()
58    }
59}
60
61impl TrackedSubstateValue {
62    pub fn size(&self) -> usize {
63        match self {
64            TrackedSubstateValue::New(x) => x.value.len(),
65            TrackedSubstateValue::ReadOnly(r) => match r {
66                ReadOnly::NonExistent => 0,
67                ReadOnly::Existent(x) => x.value.len(),
68            },
69            TrackedSubstateValue::ReadExistAndWrite(e, w) => {
70                e.len()
71                    + match w {
72                        Write::Update(x) => x.value.len(),
73                        Write::Delete => 0,
74                    }
75            }
76            TrackedSubstateValue::ReadNonExistAndWrite(x) => x.value.len(),
77            TrackedSubstateValue::WriteOnly(w) => match w {
78                Write::Update(x) => x.value.len(),
79                Write::Delete => 0,
80            },
81            TrackedSubstateValue::Garbage => 0,
82        }
83    }
84
85    pub fn get_runtime_substate_mut(&mut self) -> Option<&mut RuntimeSubstate> {
86        match self {
87            TrackedSubstateValue::New(substate)
88            | TrackedSubstateValue::WriteOnly(Write::Update(substate))
89            | TrackedSubstateValue::ReadOnly(ReadOnly::Existent(substate))
90            | TrackedSubstateValue::ReadExistAndWrite(_, Write::Update(substate))
91            | TrackedSubstateValue::ReadNonExistAndWrite(substate) => Some(substate),
92
93            TrackedSubstateValue::WriteOnly(Write::Delete)
94            | TrackedSubstateValue::ReadExistAndWrite(_, Write::Delete)
95            | TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent)
96            | TrackedSubstateValue::Garbage => None,
97        }
98    }
99
100    pub fn get(&self) -> Option<&IndexedScryptoValue> {
101        match self {
102            TrackedSubstateValue::New(substate)
103            | TrackedSubstateValue::WriteOnly(Write::Update(substate))
104            | TrackedSubstateValue::ReadOnly(ReadOnly::Existent(substate))
105            | TrackedSubstateValue::ReadExistAndWrite(_, Write::Update(substate))
106            | TrackedSubstateValue::ReadNonExistAndWrite(substate) => Some(&substate.value),
107            TrackedSubstateValue::WriteOnly(Write::Delete)
108            | TrackedSubstateValue::ReadExistAndWrite(_, Write::Delete)
109            | TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent)
110            | TrackedSubstateValue::Garbage => None,
111        }
112    }
113
114    pub fn set(&mut self, value: IndexedScryptoValue) {
115        match self {
116            TrackedSubstateValue::Garbage => {
117                *self = TrackedSubstateValue::WriteOnly(Write::Update(RuntimeSubstate::new(value)));
118            }
119            TrackedSubstateValue::New(substate)
120            | TrackedSubstateValue::WriteOnly(Write::Update(substate))
121            | TrackedSubstateValue::ReadExistAndWrite(_, Write::Update(substate))
122            | TrackedSubstateValue::ReadNonExistAndWrite(substate) => {
123                substate.value = value;
124            }
125            TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent) => {
126                let new_tracked =
127                    TrackedSubstateValue::ReadNonExistAndWrite(RuntimeSubstate::new(value));
128                *self = new_tracked;
129            }
130            TrackedSubstateValue::ReadOnly(ReadOnly::Existent(old)) => {
131                let new_tracked = TrackedSubstateValue::ReadExistAndWrite(
132                    old.value.clone(),
133                    Write::Update(RuntimeSubstate::new(value)),
134                );
135                *self = new_tracked;
136            }
137            TrackedSubstateValue::ReadExistAndWrite(_, write @ Write::Delete)
138            | TrackedSubstateValue::WriteOnly(write @ Write::Delete) => {
139                *write = Write::Update(RuntimeSubstate::new(value));
140            }
141        };
142    }
143
144    pub fn take(&mut self) -> Option<IndexedScryptoValue> {
145        match self {
146            TrackedSubstateValue::Garbage => None,
147            TrackedSubstateValue::New(..) => {
148                let old = mem::replace(self, TrackedSubstateValue::Garbage);
149                old.into_value()
150            }
151            TrackedSubstateValue::WriteOnly(_) => {
152                let old = mem::replace(self, TrackedSubstateValue::WriteOnly(Write::Delete));
153                old.into_value()
154            }
155            TrackedSubstateValue::ReadExistAndWrite(_, write) => {
156                let write = mem::replace(write, Write::Delete);
157                write.into_value()
158            }
159            TrackedSubstateValue::ReadNonExistAndWrite(..) => {
160                let old = mem::replace(self, TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent));
161                old.into_value()
162            }
163            TrackedSubstateValue::ReadOnly(ReadOnly::Existent(v)) => {
164                let new_tracked =
165                    TrackedSubstateValue::ReadExistAndWrite(v.value.clone(), Write::Delete);
166                let old = mem::replace(self, new_tracked);
167                old.into_value()
168            }
169            TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent) => None,
170        }
171    }
172
173    fn revert_writes(&mut self) {
174        match self {
175            TrackedSubstateValue::ReadOnly(..) | TrackedSubstateValue::Garbage => {}
176            TrackedSubstateValue::New(..) | TrackedSubstateValue::WriteOnly(_) => {
177                *self = TrackedSubstateValue::Garbage;
178            }
179            TrackedSubstateValue::ReadExistAndWrite(read, _) => {
180                *self = TrackedSubstateValue::ReadOnly(ReadOnly::Existent(RuntimeSubstate::new(
181                    read.clone(),
182                )));
183            }
184            TrackedSubstateValue::ReadNonExistAndWrite(..) => {
185                *self = TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent);
186            }
187        }
188    }
189
190    pub fn into_value(self) -> Option<IndexedScryptoValue> {
191        match self {
192            TrackedSubstateValue::New(substate)
193            | TrackedSubstateValue::WriteOnly(Write::Update(substate))
194            | TrackedSubstateValue::ReadOnly(ReadOnly::Existent(substate))
195            | TrackedSubstateValue::ReadNonExistAndWrite(substate)
196            | TrackedSubstateValue::ReadExistAndWrite(_, Write::Update(substate)) => {
197                Some(substate.value)
198            }
199            TrackedSubstateValue::WriteOnly(Write::Delete)
200            | TrackedSubstateValue::ReadExistAndWrite(_, Write::Delete)
201            | TrackedSubstateValue::ReadOnly(ReadOnly::NonExistent)
202            | TrackedSubstateValue::Garbage => None,
203        }
204    }
205}
206
207#[derive(Debug)]
208pub struct TrackedPartition {
209    pub substates: BTreeMap<DbSortKey, TrackedSubstate>,
210    pub range_read: u32,
211}
212
213impl TrackedPartition {
214    pub fn new() -> Self {
215        Self {
216            substates: BTreeMap::new(),
217            range_read: 0,
218        }
219    }
220
221    pub fn new_with_substates(substates: BTreeMap<DbSortKey, TrackedSubstate>) -> Self {
222        Self {
223            substates,
224            range_read: 0,
225        }
226    }
227
228    pub fn revert_writes(&mut self) {
229        for substate in &mut self.substates.values_mut() {
230            substate.substate_value.revert_writes();
231        }
232    }
233}
234
235#[derive(Debug)]
236pub struct TrackedNode {
237    pub tracked_partitions: IndexMap<PartitionNumber, TrackedPartition>,
238    // If true, then all SubstateUpdates under this NodeUpdate must be inserts
239    // The extra information, though awkward structurally, makes for a much
240    // simpler iteration implementation as long as the invariant is maintained
241    pub is_new: bool,
242}
243
244impl TrackedNode {
245    pub fn new(is_new: bool) -> Self {
246        Self {
247            tracked_partitions: index_map_new(),
248            is_new,
249        }
250    }
251
252    pub fn revert_writes(&mut self) {
253        for (_, tracked_partition) in &mut self.tracked_partitions {
254            tracked_partition.revert_writes();
255        }
256    }
257}
258
259pub struct IterationCountedIter<'a, E> {
260    pub iter:
261        Box<dyn Iterator<Item = Result<(DbSortKey, (SubstateKey, IndexedScryptoValue)), E>> + 'a>,
262    pub num_iterations: u32,
263}
264
265impl<'a, E> IterationCountedIter<'a, E> {
266    pub fn new(
267        iter: Box<
268            dyn Iterator<Item = Result<(DbSortKey, (SubstateKey, IndexedScryptoValue)), E>> + 'a,
269        >,
270    ) -> Self {
271        Self {
272            iter,
273            num_iterations: 0u32,
274        }
275    }
276}
277
278impl<'a, E> Iterator for IterationCountedIter<'a, E> {
279    type Item = Result<(DbSortKey, (SubstateKey, IndexedScryptoValue)), E>;
280
281    fn next(&mut self) -> Option<Self::Item> {
282        self.num_iterations = self.num_iterations + 1;
283        self.iter.next()
284    }
285}