Skip to main content

state_tree/
lib.rs

1pub mod patch;
2pub mod tree;
3pub mod tree_diff;
4
5use crate::patch::CopyFromPatch;
6use crate::tree::{SizedType, StateTreeSkeleton};
7
8#[derive(Debug, Clone, PartialEq, Eq)]
9pub struct StateStoragePatchPlan {
10    pub total_size: usize,
11    pub patches: Vec<CopyFromPatch>,
12}
13
14pub fn build_state_storage_patch_plan<T: SizedType + PartialEq>(
15    old_state_skeleton: StateTreeSkeleton<T>,
16    new_state_skeleton: StateTreeSkeleton<T>,
17) -> Option<StateStoragePatchPlan> {
18    if old_state_skeleton == new_state_skeleton {
19        return None;
20    }
21
22    let total_size = new_state_skeleton.total_size() as usize;
23    let patches = tree_diff::take_diff(&old_state_skeleton, &new_state_skeleton)
24        .into_iter()
25        .collect::<Vec<_>>();
26
27    Some(StateStoragePatchPlan {
28        total_size,
29        patches,
30    })
31}
32
33pub fn apply_state_storage_patch_plan(
34    old_storage: &[u64],
35    patch_plan: &StateStoragePatchPlan,
36) -> Vec<u64> {
37    let mut new_storage = vec![0u64; patch_plan.total_size];
38    patch::apply_patches(&mut new_storage, old_storage, patch_plan.patches.as_slice());
39
40    debug_assert_eq!(new_storage.len(), patch_plan.total_size);
41
42    new_storage
43}
44
45pub fn update_state_storage<T: SizedType + PartialEq>(
46    old: &[u64],
47    old_state_skeleton: StateTreeSkeleton<T>,
48    new_state_skeleton: StateTreeSkeleton<T>,
49) -> Result<Option<Vec<u64>>, Box<dyn std::error::Error>> {
50    let patch_plan = build_state_storage_patch_plan(old_state_skeleton, new_state_skeleton);
51    if let Some(plan) = patch_plan {
52        for patch in &plan.patches {
53            log::debug!("Patch: {patch:?}");
54        }
55
56        Ok(Some(apply_state_storage_patch_plan(old, &plan)))
57    } else {
58        Ok(None)
59    }
60}