cfx_statedb/
statedb_ext.rs

1// Copyright 2020 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
5use cfx_parameters::internal_contract_addresses::SYSTEM_STORAGE_ADDRESS;
6use rlp::Rlp;
7
8use cfx_internal_common::debug::ComputeEpochDebugRecord;
9use cfx_types::{AddressWithSpace, H256, U256};
10use primitives::{
11    is_default::IsDefault, Account, CodeInfo, DepositList, StorageKey,
12    StorageKeyWithSpace, VoteStakeList,
13};
14
15use crate::global_params::{GlobalParamKey, InterestRate};
16
17use super::{Result, StateDbGeneric};
18
19pub trait StateDbExt {
20    fn get<T>(&self, key: StorageKeyWithSpace) -> Result<Option<T>>
21    where T: ::rlp::Decodable;
22
23    fn set<T>(
24        &mut self, key: StorageKeyWithSpace, value: &T,
25        debug_record: Option<&mut ComputeEpochDebugRecord>,
26    ) -> Result<()>
27    where
28        T: ::rlp::Encodable + IsDefault;
29
30    fn get_account(
31        &self, address: &AddressWithSpace,
32    ) -> Result<Option<Account>>;
33
34    fn get_code(
35        &self, address: &AddressWithSpace, code_hash: &H256,
36    ) -> Result<Option<CodeInfo>>;
37
38    fn get_deposit_list(
39        &self, address: &AddressWithSpace,
40    ) -> Result<Option<DepositList>>;
41
42    fn get_vote_list(
43        &self, address: &AddressWithSpace,
44    ) -> Result<Option<VoteStakeList>>;
45
46    fn get_system_storage(&self, key: &[u8]) -> Result<U256>;
47
48    fn get_global_param<T: GlobalParamKey>(&self) -> Result<U256>;
49    fn set_global_param<T: GlobalParamKey>(
50        &mut self, value: &U256,
51        debug_record: Option<&mut ComputeEpochDebugRecord>,
52    ) -> Result<()>;
53
54    // This function is used to check whether the db has been initialized when
55    // create a state. So we can know the loaded `None` represents "not
56    // initialized" or "zero value".
57    fn is_initialized(&self) -> Result<bool>;
58}
59
60impl StateDbExt for StateDbGeneric {
61    fn get<T>(&self, key: StorageKeyWithSpace) -> Result<Option<T>>
62    where T: ::rlp::Decodable {
63        match self.get_raw(key) {
64            Ok(None) => Ok(None),
65            Ok(Some(raw)) => Ok(Some(::rlp::decode::<T>(raw.as_ref())?)),
66            Err(e) => bail!(e),
67        }
68    }
69
70    fn set<T>(
71        &mut self, key: StorageKeyWithSpace, value: &T,
72        debug_record: Option<&mut ComputeEpochDebugRecord>,
73    ) -> Result<()>
74    where
75        T: ::rlp::Encodable + IsDefault,
76    {
77        if value.is_default() {
78            self.delete(key, debug_record)
79        } else {
80            self.set_raw(
81                key,
82                ::rlp::encode(value).into_boxed_slice(),
83                debug_record,
84            )
85        }
86    }
87
88    fn get_account(
89        &self, address: &AddressWithSpace,
90    ) -> Result<Option<Account>> {
91        match self.get_raw(
92            StorageKey::new_account_key(&address.address)
93                .with_space(address.space),
94        ) {
95            Ok(None) => Ok(None),
96            Ok(Some(raw)) => Ok(Some(Account::new_from_rlp(
97                address.address,
98                &Rlp::new(&raw),
99            )?)),
100            Err(e) => bail!(e),
101        }
102    }
103
104    fn get_code(
105        &self, address: &AddressWithSpace, code_hash: &H256,
106    ) -> Result<Option<CodeInfo>> {
107        self.get::<CodeInfo>(
108            StorageKey::new_code_key(&address.address, code_hash)
109                .with_space(address.space),
110        )
111    }
112
113    fn get_deposit_list(
114        &self, address: &AddressWithSpace,
115    ) -> Result<Option<DepositList>> {
116        address.assert_native();
117        self.get::<DepositList>(
118            StorageKey::new_deposit_list_key(&address.address)
119                .with_native_space(),
120        )
121    }
122
123    fn get_vote_list(
124        &self, address: &AddressWithSpace,
125    ) -> Result<Option<VoteStakeList>> {
126        address.assert_native();
127        self.get::<VoteStakeList>(
128            StorageKey::new_vote_list_key(&address.address).with_native_space(),
129        )
130    }
131
132    fn get_global_param<T: GlobalParamKey>(&self) -> Result<U256> {
133        Ok(self.get::<U256>(T::STORAGE_KEY)?.unwrap_or_default())
134    }
135
136    fn get_system_storage(&self, key: &[u8]) -> Result<U256> {
137        let storage_key = StorageKey::StorageKey {
138            address_bytes: SYSTEM_STORAGE_ADDRESS.as_bytes(),
139            storage_key: key,
140        }
141        .with_native_space();
142        Ok(self.get::<U256>(storage_key)?.unwrap_or_default())
143    }
144
145    fn set_global_param<T: GlobalParamKey>(
146        &mut self, value: &U256,
147        debug_record: Option<&mut ComputeEpochDebugRecord>,
148    ) -> Result<()> {
149        self.set::<U256>(T::STORAGE_KEY, value, debug_record)
150    }
151
152    fn is_initialized(&self) -> Result<bool> {
153        let interest_rate_opt = self.get::<U256>(InterestRate::STORAGE_KEY)?;
154        Ok(interest_rate_opt.is_some())
155    }
156}