cfxcore/consensus/consensus_graph/rpc_api/
state_provider.rs1use crate::errors::{invalid_params_check, Result as CoreResult};
2
3use cfx_statedb::StateDb;
4use cfx_storage::{
5 state::StateTrait, state_manager::StateManagerTrait, StorageState,
6};
7use cfx_types::{Space, H256};
8
9use primitives::EpochNumber;
10
11use super::super::ConsensusGraph;
12
13impl ConsensusGraph {
14 pub fn get_storage_state_by_epoch_number(
15 &self, epoch_number: EpochNumber, rpc_param_name: &str,
16 ) -> CoreResult<StorageState> {
17 invalid_params_check(
18 rpc_param_name,
19 self.validate_stated_epoch(&epoch_number),
20 )?;
21 let height = invalid_params_check(
22 rpc_param_name,
23 self.get_height_from_epoch_number(epoch_number),
24 )?;
25 let hash =
26 self.inner.read().get_pivot_hash_from_epoch_number(height)?;
27 self.get_storage_state_by_height_and_hash(height, &hash)
28 }
29
30 pub fn get_eth_state_db_by_epoch_number(
31 &self, epoch_number: EpochNumber, rpc_param_name: &str,
32 ) -> CoreResult<StateDb> {
33 self.get_state_db_by_epoch_number_with_space(
34 epoch_number,
35 rpc_param_name,
36 Some(Space::Ethereum),
37 )
38 }
39
40 pub fn get_state_db_by_epoch_number(
41 &self, epoch_number: EpochNumber, rpc_param_name: &str,
42 ) -> CoreResult<StateDb> {
43 self.get_state_db_by_epoch_number_with_space(
44 epoch_number,
45 rpc_param_name,
46 None,
47 )
48 }
49
50 fn get_state_db_by_epoch_number_with_space(
51 &self, epoch_number: EpochNumber, rpc_param_name: &str,
52 space: Option<Space>,
53 ) -> CoreResult<StateDb> {
54 invalid_params_check(
55 rpc_param_name,
56 self.validate_stated_epoch(&epoch_number),
57 )?;
58 let height = invalid_params_check(
59 rpc_param_name,
60 self.get_height_from_epoch_number(epoch_number),
61 )?;
62 let hash =
63 self.inner.read().get_pivot_hash_from_epoch_number(height)?;
64 Ok(StateDb::new(
65 self.get_state_by_height_and_hash(height, &hash, space)?,
66 ))
67 }
68
69 fn get_storage_state_by_height_and_hash(
70 &self, height: u64, hash: &H256,
71 ) -> CoreResult<StorageState> {
72 let state_availability_boundary =
75 self.data_man.state_availability_boundary.read();
76 if !state_availability_boundary.check_availability(height, &hash) {
77 debug!(
78 "State for epoch (number={:?} hash={:?}) does not exist: out-of-bound {:?}",
79 height, hash, state_availability_boundary
80 );
81 bail!(format!(
82 "State for epoch (number={:?} hash={:?}) does not exist: out-of-bound {:?}",
83 height, hash, state_availability_boundary
84 ));
85 }
86 let maybe_state_readonly_index =
87 self.data_man.get_state_readonly_index(&hash).into();
88 let maybe_state = match maybe_state_readonly_index {
89 Some(state_readonly_index) => self
90 .data_man
91 .storage_manager
92 .get_state_no_commit_inner(
93 state_readonly_index,
94 true,
95 true,
96 )
97 .map_err(|e| format!("Error to get state, err={:?}", e))?,
98 None => None,
99 };
100
101 let state = match maybe_state {
102 Some(state) => state,
103 None => {
104 bail!(format!(
105 "State for epoch (number={:?} hash={:?}) does not exist",
106 height, hash
107 ));
108 }
109 };
110
111 Ok(state)
112 }
113
114 fn get_state_by_height_and_hash(
115 &self, height: u64, hash: &H256, space: Option<Space>,
116 ) -> CoreResult<Box<dyn StateTrait>> {
117 let state_availability_boundary =
120 self.data_man.state_availability_boundary.read();
121 if !state_availability_boundary
122 .check_read_availability(height, &hash, space)
123 {
124 debug!(
125 "State for epoch (number={:?} hash={:?}) does not exist: out-of-bound {:?}",
126 height, hash, state_availability_boundary
127 );
128 bail!(format!(
129 "State for epoch (number={:?} hash={:?}) does not exist: out-of-bound {:?}",
130 height, hash, state_availability_boundary
131 ));
132 }
133 let maybe_state_readonly_index =
134 self.data_man.get_state_readonly_index(&hash).into();
135 let maybe_state = match maybe_state_readonly_index {
136 Some(state_readonly_index) => self
137 .data_man
138 .storage_manager
139 .get_state_no_commit(
140 state_readonly_index,
141 true,
142 space,
143 )
144 .map_err(|e| format!("Error to get state, err={:?}", e))?,
145 None => None,
146 };
147
148 let state = match maybe_state {
149 Some(state) => state,
150 None => {
151 bail!(format!(
152 "State for epoch (number={:?} hash={:?}) does not exist",
153 height, hash
154 ));
155 }
156 };
157
158 Ok(state)
159 }
160}