1use crate::internal_prelude::*;
2
3#[derive(Debug, Clone, PartialEq, Eq, Sbor, Default)]
13pub struct StateUpdates {
14 pub by_node: IndexMap<NodeId, NodeStateUpdates>,
16}
17
18impl StateUpdates {
19 pub fn empty() -> Self {
20 Self {
21 by_node: Default::default(),
22 }
23 }
24
25 pub fn of_node(&mut self, node_id: impl Into<NodeId>) -> &mut NodeStateUpdates {
27 self.by_node
28 .entry(node_id.into())
29 .or_insert_with(|| NodeStateUpdates::Delta {
30 by_partition: index_map_new(),
31 })
32 }
33
34 pub fn set_node_updates(
35 mut self,
36 node_id: impl Into<NodeId>,
37 node_updates: NodeStateUpdates,
38 ) -> Self {
39 self.by_node.insert(node_id.into(), node_updates);
40 self
41 }
42
43 pub fn set_substate<'a>(
44 mut self,
45 node_id: impl Into<NodeId>,
46 partition_num: PartitionNumber,
47 substate_key: impl ResolvableSubstateKey<'a>,
48 new_value: impl ScryptoEncode,
49 ) -> Self {
50 let new_value = scrypto_encode(&new_value).expect("New substate value should be encodable");
51 self.of_node(node_id.into())
52 .of_partition(partition_num)
53 .mut_update_substates([(
54 substate_key.into_substate_key(),
55 DatabaseUpdate::Set(new_value),
56 )]);
57 self
58 }
59
60 pub fn mut_add_node_updates(
61 &mut self,
62 node_id: impl Into<NodeId>,
63 node_updates: impl Into<NodeStateUpdates>,
64 ) {
65 let Some(node_updates) = node_updates.into().rebuild_without_empty_entries() else {
66 return;
67 };
68 self.of_node(node_id).mut_add_updates(node_updates);
69 }
70
71 pub fn rebuild_without_empty_entries(self) -> Self {
72 Self {
73 by_node: self
74 .by_node
75 .into_iter()
76 .filter_map(|(node_id, by_partition)| {
77 let by_partition = by_partition.rebuild_without_empty_entries()?;
78 Some((node_id, by_partition))
79 })
80 .collect(),
81 }
82 }
83
84 pub fn into_flattened_substate_updates(
87 self,
88 ) -> IndexMap<(NodeId, PartitionNumber, SubstateKey), DatabaseUpdate> {
89 let mut substate_updates = index_map_new();
90 for (node_id, node_state_updates) in self.by_node {
91 match node_state_updates {
92 NodeStateUpdates::Delta { by_partition } => {
93 for (partition_num, partition_state_updates) in by_partition {
94 match partition_state_updates {
95 PartitionStateUpdates::Delta { by_substate } => {
96 for (key, value) in by_substate {
97 substate_updates.insert((node_id, partition_num, key), value);
98 }
99 }
100 PartitionStateUpdates::Batch(batch) => match batch {
101 BatchPartitionStateUpdate::Reset {
102 new_substate_values,
103 } => {
104 for (key, value) in new_substate_values {
105 substate_updates.insert(
106 (node_id, partition_num, key),
107 DatabaseUpdate::Set(value),
108 );
109 }
110 }
111 },
112 }
113 }
114 }
115 }
116 }
117 substate_updates
118 }
119}
120
121#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
125pub enum NodeStateUpdates {
126 Delta {
130 by_partition: IndexMap<PartitionNumber, PartitionStateUpdates>,
131 },
132}
133
134impl Default for NodeStateUpdates {
135 fn default() -> Self {
136 NodeStateUpdates::Delta {
137 by_partition: index_map_new(),
138 }
139 }
140}
141
142impl NodeStateUpdates {
143 pub fn empty() -> Self {
144 Self::Delta {
145 by_partition: Default::default(),
146 }
147 }
148
149 pub fn set_substate<'a>(
150 mut self,
151 partition_num: PartitionNumber,
152 key: impl ResolvableSubstateKey<'a>,
153 value: impl ScryptoEncode,
154 ) -> Self {
155 self.mut_set_substate(partition_num, key, value);
156 self
157 }
158
159 pub fn mut_set_substate<'a>(
160 &mut self,
161 partition_num: PartitionNumber,
162 key: impl ResolvableSubstateKey<'a>,
163 value: impl ScryptoEncode,
164 ) {
165 let Self::Delta {
166 ref mut by_partition,
167 } = self;
168 by_partition
169 .entry(partition_num)
170 .or_default()
171 .mut_set_substate(key.into_substate_key(), value);
172 }
173
174 pub fn mut_add_updates(&mut self, other: impl Into<Self>) {
175 let Self::Delta {
176 by_partition: other_by_partition,
177 } = other.into();
178 for (partition_number, partition_state_updates) in other_by_partition {
179 if partition_state_updates.is_no_op() {
181 continue;
182 }
183 self.of_partition(partition_number)
184 .mut_add_updates(partition_state_updates);
185 }
186 }
187
188 pub fn of_partition(&mut self, partition_num: PartitionNumber) -> &mut PartitionStateUpdates {
190 match self {
191 NodeStateUpdates::Delta { by_partition } => {
192 by_partition.entry(partition_num).or_default()
193 }
194 }
195 }
196
197 pub fn of_partition_ref(
198 &self,
199 partition_num: PartitionNumber,
200 ) -> Option<&PartitionStateUpdates> {
201 match self {
202 NodeStateUpdates::Delta { by_partition } => by_partition.get(&partition_num),
203 }
204 }
205
206 pub fn rebuild_without_empty_entries(self) -> Option<Self> {
207 match self {
208 NodeStateUpdates::Delta { by_partition } => {
209 let replaced = by_partition
210 .into_iter()
211 .filter_map(|(partition_num, partition_state_updates)| {
212 let new_substate =
213 partition_state_updates.rebuild_without_empty_entries()?;
214 Some((partition_num, new_substate))
215 })
216 .collect::<IndexMap<_, _>>();
217 if !replaced.is_empty() {
218 Some(NodeStateUpdates::Delta {
219 by_partition: replaced,
220 })
221 } else {
222 None
223 }
224 }
225 }
226 }
227}
228
229#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
231pub enum PartitionStateUpdates {
232 Delta {
236 by_substate: IndexMap<SubstateKey, DatabaseUpdate>,
237 },
238 Batch(BatchPartitionStateUpdate),
240}
241
242impl Default for PartitionStateUpdates {
243 fn default() -> Self {
244 PartitionStateUpdates::Delta {
245 by_substate: index_map_new(),
246 }
247 }
248}
249
250impl PartitionStateUpdates {
251 pub fn is_no_op(&self) -> bool {
252 match self {
253 PartitionStateUpdates::Delta { by_substate } => by_substate.is_empty(),
254 PartitionStateUpdates::Batch(BatchPartitionStateUpdate::Reset { .. }) => false,
255 }
256 }
257
258 pub fn set_substate<'a>(
259 mut self,
260 key: impl ResolvableSubstateKey<'a>,
261 value: impl ScryptoEncode,
262 ) -> Self {
263 self.mut_set_substate(key, value);
264 self
265 }
266
267 pub fn mut_add_updates(&mut self, other: impl Into<Self>) {
268 match other.into() {
269 PartitionStateUpdates::Delta { by_substate } => {
270 self.mut_update_substates(by_substate);
271 }
272 other @ PartitionStateUpdates::Batch(BatchPartitionStateUpdate::Reset { .. }) => {
274 *self = other;
275 }
276 }
277 }
278
279 pub fn mut_set_substate<'a>(
280 &mut self,
281 key: impl ResolvableSubstateKey<'a>,
282 value: impl ScryptoEncode,
283 ) {
284 let value = scrypto_encode(&value).expect("New substate value should be encodable");
285 match self {
286 PartitionStateUpdates::Delta { by_substate } => {
287 by_substate.insert(key.into_substate_key(), DatabaseUpdate::Set(value));
288 }
289 PartitionStateUpdates::Batch(BatchPartitionStateUpdate::Reset {
290 new_substate_values,
291 }) => {
292 new_substate_values.insert(key.into_substate_key(), value);
293 }
294 }
295 }
296
297 pub fn delete(&mut self) {
299 *self = PartitionStateUpdates::Batch(BatchPartitionStateUpdate::Reset {
300 new_substate_values: index_map_new(),
301 });
302 }
303
304 pub fn contains_set_update_for(&self, key: &SubstateKey) -> bool {
305 match self {
306 PartitionStateUpdates::Delta { by_substate } => {
307 matches!(by_substate.get(key), Some(DatabaseUpdate::Set(_)))
308 }
309 PartitionStateUpdates::Batch(BatchPartitionStateUpdate::Reset {
310 new_substate_values,
311 }) => new_substate_values.contains_key(key),
312 }
313 }
314
315 pub fn mut_update_substate<'a>(
316 &mut self,
317 key: impl ResolvableSubstateKey<'a>,
318 database_update: DatabaseUpdate,
319 ) {
320 let substate_key = key.into_substate_key();
321 match self {
322 PartitionStateUpdates::Delta { by_substate } => {
323 by_substate.insert(substate_key, database_update);
324 }
325 PartitionStateUpdates::Batch(batch_updates) => {
326 batch_updates.mut_update_substate(substate_key, database_update);
327 }
328 }
329 }
330
331 pub fn update_substate<'a>(
332 mut self,
333 key: impl ResolvableSubstateKey<'a>,
334 database_update: DatabaseUpdate,
335 ) -> Self {
336 self.mut_update_substate(key, database_update);
337 self
338 }
339
340 pub fn mut_update_substates(
342 &mut self,
343 updates: impl IntoIterator<Item = (SubstateKey, DatabaseUpdate)>,
344 ) {
345 match self {
346 PartitionStateUpdates::Delta { by_substate } => {
347 by_substate.extend(updates);
348 }
349 PartitionStateUpdates::Batch(batch_updates) => {
350 batch_updates.mut_update_substates(updates);
351 }
352 }
353 }
354
355 pub fn update_substates(
356 mut self,
357 updates: impl IntoIterator<Item = (SubstateKey, DatabaseUpdate)>,
358 ) -> Self {
359 self.mut_update_substates(updates);
360 self
361 }
362
363 pub fn rebuild_without_empty_entries(self) -> Option<Self> {
364 match self {
365 PartitionStateUpdates::Delta { ref by_substate } => {
366 if !by_substate.is_empty() {
367 Some(self)
368 } else {
369 None
370 }
371 }
372 PartitionStateUpdates::Batch(_) => {
373 Some(self)
375 }
376 }
377 }
378
379 pub fn iter_map_entries(
380 &self,
381 ) -> Box<dyn Iterator<Item = (&MapKey, DatabaseUpdateRef<'_>)> + '_> {
382 match self {
383 PartitionStateUpdates::Delta { by_substate } => {
384 Box::new(by_substate.iter().filter_map(|(key, value)| match key {
385 SubstateKey::Map(map_key) => {
386 let value = match value {
387 DatabaseUpdate::Set(value) => DatabaseUpdateRef::Set(value),
388 DatabaseUpdate::Delete => DatabaseUpdateRef::Delete,
389 };
390 Some((map_key, value))
391 }
392 SubstateKey::Field(_) | SubstateKey::Sorted(_) => None,
393 }))
394 }
395 PartitionStateUpdates::Batch(BatchPartitionStateUpdate::Reset {
396 new_substate_values,
397 }) => Box::new(
398 new_substate_values
399 .iter()
400 .filter_map(|(key, value)| match key {
401 SubstateKey::Map(map_key) => Some((map_key, DatabaseUpdateRef::Set(value))),
402 SubstateKey::Field(_) | SubstateKey::Sorted(_) => None,
403 }),
404 ),
405 }
406 }
407}
408
409#[derive(Debug, Clone, PartialEq, Eq, Sbor)]
411pub enum BatchPartitionStateUpdate {
412 Reset {
415 new_substate_values: IndexMap<SubstateKey, DbSubstateValue>,
416 },
417}
418
419impl BatchPartitionStateUpdate {
420 pub fn mut_update_substates(
421 &mut self,
422 updates: impl IntoIterator<Item = (SubstateKey, DatabaseUpdate)>,
423 ) {
424 for (substate_key, database_update) in updates {
425 self.mut_update_substate(substate_key, database_update);
426 }
427 }
428
429 pub fn mut_update_substate(
430 &mut self,
431 substate_key: SubstateKey,
432 database_update: DatabaseUpdate,
433 ) {
434 let BatchPartitionStateUpdate::Reset {
435 new_substate_values,
436 } = self;
437 match database_update {
438 DatabaseUpdate::Set(new_value) => {
439 new_substate_values.insert(substate_key, new_value);
440 }
441 DatabaseUpdate::Delete => {
442 new_substate_values.swap_remove(&substate_key);
443 }
444 }
445 }
446}
447
448#[derive(Debug, Clone, Hash, PartialEq, Eq, Sbor, PartialOrd, Ord)]
450pub enum DatabaseUpdate {
451 Set(DbSubstateValue),
452 Delete,
453}
454
455impl DatabaseUpdate {
456 pub fn as_ref(&self) -> DatabaseUpdateRef<'_> {
457 match self {
458 DatabaseUpdate::Set(update) => DatabaseUpdateRef::Set(update),
459 DatabaseUpdate::Delete => DatabaseUpdateRef::Delete,
460 }
461 }
462}
463
464pub enum DatabaseUpdateRef<'v> {
466 Set(&'v [u8]),
467 Delete,
468}
469
470pub type DbSubstateValue = Vec<u8>;