cfx_storage/
state_manager.rs

1// Copyright 2019 Conflux Foundation. All rights reserved.
2// Conflux is free software and distributed under GNU General Public License.
3// See http://www.gnu.org/licenses/
4
5// StateManager is the single entry-point to access State for any epoch.
6// StateManager manages internal mutability and is thread-safe.
7pub use super::impls::state_manager::StateManager;
8
9pub type SharedStateManager = Arc<StateManager>;
10
11#[derive(Debug)]
12pub struct StateIndex {
13    pub snapshot_epoch_id: EpochId,
14    pub snapshot_merkle_root: MerkleHash,
15    pub intermediate_epoch_id: EpochId,
16    pub intermediate_trie_root_merkle: MerkleHash,
17    pub maybe_intermediate_mpt_key_padding: Option<DeltaMptKeyPadding>,
18    pub epoch_id: EpochId,
19    pub delta_mpt_key_padding: DeltaMptKeyPadding,
20    pub maybe_delta_trie_height: Option<u32>,
21    pub maybe_height: Option<u64>,
22}
23
24// The trait is created to separate the implementation to another file, and the
25// concrete struct is put into inner mod, because the implementation is
26// anticipated to be too complex to present in the same file of the API.
27pub trait StateManagerTrait {
28    /// At the boundary of snapshot, getting a state for new epoch will switch
29    /// to new Delta MPT, but it's unnecessary getting a no-commit state.
30    ///
31    /// With try_open == true, the call fails immediately when the max number of
32    /// snapshot open is reached.
33    ///
34    /// If `space` is `None`, we need data from all spaces.
35    fn get_state_no_commit(
36        self: &Arc<Self>, epoch_id: StateIndex, try_open: bool,
37        space: Option<Space>,
38    ) -> Result<Option<Box<dyn StateTrait>>>;
39    fn get_state_for_next_epoch(
40        self: &Arc<Self>, parent_epoch_id: StateIndex,
41        recover_mpt_during_construct_pivot_state: bool,
42    ) -> Result<Option<Box<dyn StateTrait>>>;
43    fn get_state_for_genesis_write(self: &Arc<Self>) -> Box<dyn StateTrait>;
44}
45
46pub trait ReplicatedStateManagerTrait {
47    fn get_replicated_state_for_next_epoch(
48        self: &Arc<Self>, parent_epoch_id: StateIndex,
49    ) -> Result<Option<Box<dyn StateTrait>>>;
50    fn get_replicated_state_for_genesis_write(
51        self: &Arc<Self>,
52    ) -> Box<dyn StateTrait>;
53}
54
55impl StateIndex {
56    pub fn height_to_delta_height(
57        height: u64, snapshot_epoch_count: u32,
58    ) -> u32 {
59        if height == 0 {
60            0
61        } else {
62            ((height - 1) % (snapshot_epoch_count as u64)) as u32 + 1
63        }
64    }
65
66    pub fn new_for_test_only_delta_mpt(epoch_id: &EpochId) -> Self {
67        Self {
68            snapshot_epoch_id: NULL_EPOCH,
69            snapshot_merkle_root: MERKLE_NULL_NODE,
70            intermediate_epoch_id: NULL_EPOCH,
71            intermediate_trie_root_merkle: MERKLE_NULL_NODE,
72            maybe_intermediate_mpt_key_padding: None,
73            epoch_id: *epoch_id,
74            delta_mpt_key_padding: GENESIS_DELTA_MPT_KEY_PADDING.clone(),
75            maybe_delta_trie_height: Some(0),
76            maybe_height: Some(0),
77        }
78    }
79
80    /// Height is used to check for shifting snapshot.
81    /// The state root and height information should be provided from consensus.
82    pub fn new_for_next_epoch(
83        base_epoch_id: &EpochId, state_root: &StateRootWithAuxInfo,
84        height: u64, snapshot_epoch_count: u32,
85    ) -> Self {
86        Self {
87            snapshot_epoch_id: state_root.aux_info.snapshot_epoch_id,
88            snapshot_merkle_root: state_root.state_root.snapshot_root,
89            intermediate_epoch_id: state_root.aux_info.intermediate_epoch_id,
90            intermediate_trie_root_merkle: state_root
91                .state_root
92                .intermediate_delta_root,
93            maybe_intermediate_mpt_key_padding: state_root
94                .aux_info
95                .maybe_intermediate_mpt_key_padding
96                .clone(),
97            epoch_id: *base_epoch_id,
98            delta_mpt_key_padding: state_root
99                .aux_info
100                .delta_mpt_key_padding
101                .clone(),
102            maybe_delta_trie_height: Some(Self::height_to_delta_height(
103                height,
104                snapshot_epoch_count,
105            )),
106            maybe_height: Some(height),
107        }
108    }
109
110    pub fn new_for_readonly(
111        epoch_id: &EpochId, state_root: &StateRootWithAuxInfo,
112    ) -> Self {
113        Self {
114            snapshot_epoch_id: state_root.aux_info.snapshot_epoch_id,
115            snapshot_merkle_root: state_root.state_root.snapshot_root,
116            intermediate_epoch_id: state_root.aux_info.intermediate_epoch_id,
117            intermediate_trie_root_merkle: state_root
118                .state_root
119                .intermediate_delta_root,
120            maybe_intermediate_mpt_key_padding: state_root
121                .aux_info
122                .maybe_intermediate_mpt_key_padding
123                .clone(),
124            epoch_id: *epoch_id,
125            delta_mpt_key_padding: state_root
126                .aux_info
127                .delta_mpt_key_padding
128                .clone(),
129            maybe_delta_trie_height: None,
130            maybe_height: None,
131        }
132    }
133}
134
135use crate::{impls::errors::*, state::StateTrait, StateRootWithAuxInfo};
136use cfx_types::Space;
137use primitives::{
138    DeltaMptKeyPadding, EpochId, MerkleHash, GENESIS_DELTA_MPT_KEY_PADDING,
139    MERKLE_NULL_NODE, NULL_EPOCH,
140};
141use std::sync::Arc;