ab_client_consensus_common/
state.rs1#[cfg(test)]
2mod tests;
3
4use ab_aligned_buffer::SharedAlignedBuffer;
5use ab_client_api::ContractSlotState;
6use ab_core_primitives::address::Address;
7use ab_core_primitives::hashes::Blake3Hash;
8use ab_core_primitives::trees::{StateOwnerContractsSparseMerkleTree, StateOwnersSparseMerkleTree};
9use ab_merkle_tree::sparse::Leaf;
10use blake3::hash;
11use std::collections::BTreeMap;
12use std::mem::MaybeUninit;
13use std::num::NonZeroU128;
14use triomphe::{Arc, UniqueArc};
15
16#[derive(Debug, Clone)]
18pub struct GlobalState {
19 state: BTreeMap<Address, BTreeMap<Address, SharedAlignedBuffer>>,
21 total_len: usize,
22}
23
24impl GlobalState {
25 pub fn new(system_contract_states: &[ContractSlotState]) -> Self {
26 let mut state = BTreeMap::<Address, BTreeMap<_, _>>::new();
27 for system_contract_state in system_contract_states {
28 state
29 .entry(system_contract_state.owner)
30 .or_default()
31 .insert(
32 system_contract_state.contract,
33 system_contract_state.contents.clone(),
34 );
35 }
36
37 Self {
38 state,
39 total_len: system_contract_states.len(),
40 }
41 }
42
43 pub fn to_system_contract_states(&self) -> Arc<[ContractSlotState]> {
44 let mut system_contract_states =
45 UniqueArc::<[MaybeUninit<ContractSlotState>]>::new_uninit_slice(self.total_len);
46
47 self.state
48 .iter()
49 .flat_map(|(owner, state)| {
50 state.iter().map(|(contract, contents)| ContractSlotState {
51 owner: *owner,
52 contract: *contract,
53 contents: contents.clone(),
54 })
55 })
56 .zip(system_contract_states.iter_mut())
57 .for_each(|(input, output)| {
58 output.write(input);
59 });
60
61 unsafe { UniqueArc::assume_init_slice(system_contract_states) }.shareable()
64 }
65
66 pub fn root(&self) -> Blake3Hash {
67 let mut previous_owner = None;
68
69 let maybe_state_root = StateOwnersSparseMerkleTree::compute_root_only(
70 self.state.iter().flat_map(|(&owner, state)| {
71 let owner = u128::from(owner);
72 let skip_count = match previous_owner.replace(owner) {
74 Some(previous_owner) => owner - previous_owner - 1,
75 None => owner,
76 };
77 let skip_leaf =
78 NonZeroU128::new(skip_count).map(|skip_count| Leaf::Empty { skip_count });
79
80 let mut previous_contract = None;
81
82 let maybe_owner_root = StateOwnerContractsSparseMerkleTree::compute_root_only(
83 state.iter().flat_map(|(&contract, contents)| {
84 let contract = u128::from(contract);
85 let skip_count = match previous_contract.replace(contract) {
87 Some(previous_contract) => contract - previous_contract - 1,
88 None => contract,
89 };
90 let skip_leaf = NonZeroU128::new(skip_count)
91 .map(|skip_count| Leaf::Empty { skip_count });
92
93 skip_leaf.into_iter().chain([Leaf::OccupiedOwned {
94 leaf: *hash(contents.as_slice()).as_bytes(),
95 }])
96 }),
97 );
98 let owner_root = maybe_owner_root.expect(
99 "The number of leaves is limited by address space, which is 128-bit; qed",
100 );
101
102 skip_leaf
103 .into_iter()
104 .chain([Leaf::OccupiedOwned { leaf: owner_root }])
105 }),
106 );
107 let state_root = maybe_state_root
108 .expect("The number of leaves is limited by address space, which is 128-bit; qed");
109
110 Blake3Hash::new(state_root)
111 }
112}