cfx_executor/state/overlay_account/
storage.rs1use super::Substate;
2
3#[cfg(test)]
4use super::StorageLayout;
5use cfx_parameters::{
6 internal_contract_addresses::SYSTEM_STORAGE_ADDRESS,
7 staking::COLLATERAL_UNITS_PER_STORAGE_KEY,
8};
9use cfx_statedb::{Result as DbResult, StateDbExt, StateDbGeneric};
10use cfx_types::{Address, Space, U256};
11
12use primitives::{
13 storage::WriteCacheItem, SkipInputCheck, StorageKey, StorageKeyWithSpace,
14 StorageValue,
15};
16use std::collections::{hash_map::Entry::*, HashSet};
17
18use super::OverlayAccount;
19
20#[cfg(test)]
21use super::super::checkpoints::CheckpointEntry;
22
23impl OverlayAccount {
24 pub fn set_storage(
25 &mut self, key: Vec<u8>, value: U256, old_value: StorageValue,
26 owner: Address, substate: &mut Substate,
27 ) -> DbResult<()> {
28 if let Some(old_owner) = old_value.owner {
30 substate.record_storage_release(
31 &old_owner,
32 COLLATERAL_UNITS_PER_STORAGE_KEY,
33 );
34 }
35
36 let new_owner = if self.should_have_owner(&key) && !value.is_zero() {
38 substate.record_storage_occupy(
39 &owner,
40 COLLATERAL_UNITS_PER_STORAGE_KEY,
41 );
42 Some(owner)
43 } else {
44 None
45 };
46
47 self.insert_storage_write_cache(
48 key,
49 StorageValue {
50 owner: new_owner,
51 value,
52 },
53 );
54 Ok(())
55 }
56
57 #[cfg(test)]
58 pub fn set_storage_simple(&mut self, key: Vec<u8>, value: U256) {
59 self.insert_storage_write_cache(
60 key,
61 StorageValue { owner: None, value },
62 );
63 }
64
65 pub fn delete_storage_range(
66 &mut self, db_deletion_log: impl Iterator<Item = (Vec<u8>, Box<[u8]>)>,
67 key_prefix: &[u8], substate: &mut Substate,
68 ) -> DbResult<()> {
69 assert_eq!(self.address.space, Space::Native);
70 let delete_all = key_prefix.is_empty();
71
72 assert!(self.storage_write_checkpoint.is_none());
75 let write_cache = &mut self.storage_write_cache.write();
76 let commit_cache = &mut self.storage_committed_cache.write();
77
78 let mut read_keys = HashSet::new();
79 for (k, item) in write_cache.iter_mut() {
81 let WriteCacheItem::Write(v) = item else {
82 read_keys.insert(k.clone());
83 continue;
84 };
85 if k.starts_with(key_prefix) && !v.value.is_zero() {
86 if let Some(old_owner) = v.owner {
87 substate.record_storage_release(
88 &old_owner,
89 COLLATERAL_UNITS_PER_STORAGE_KEY,
90 );
91 };
92 *v = StorageValue::default();
93 }
94 }
95
96 for k in read_keys {
97 write_cache.remove(&k);
98 }
99
100 for (k, v) in commit_cache.iter_mut() {
101 if write_cache.get(k).is_some() {
102 continue;
103 }
104 if k.starts_with(key_prefix) && !v.value.is_zero() {
105 if let Some(old_owner) = v.owner {
106 substate.record_storage_release(
107 &old_owner,
108 COLLATERAL_UNITS_PER_STORAGE_KEY,
109 );
110 };
111 write_cache.insert(
112 k.clone(),
113 WriteCacheItem::Write(StorageValue::default()),
114 );
115 }
116 }
117
118 let read_cache = self.storage_read_cache.read();
119 for (key, raw_value) in db_deletion_log
120 .into_iter()
121 .filter_map(|(k, v)| Some((decode_storage_key(&k)?, v)))
122 {
123 match write_cache.entry(key.clone()) {
124 Vacant(entry) => {
125 if !delete_all {
129 entry.insert(WriteCacheItem::Write(
130 StorageValue::default(),
131 ));
132 }
133
134 if !delete_all && !read_cache.contains_key(&key) {
135 continue;
140 }
141 }
142 Occupied(_) => {
143 continue;
147 }
148 }
149 let StorageValue { owner, value } =
151 rlp::decode::<StorageValue>(&raw_value)?;
152 assert!(!value.is_zero());
153 let owner = owner.unwrap_or(self.address.address);
154 substate.record_storage_release(
155 &owner,
156 COLLATERAL_UNITS_PER_STORAGE_KEY,
157 );
158 }
159 std::mem::drop(read_cache);
160
161 if delete_all {
162 write_cache.clear();
163 self.storage_read_cache.write().clear();
164 self.pending_db_clear = true;
165 }
166 Ok(())
167 }
168
169 fn cached_entry_at(&self, key: &[u8]) -> Option<StorageValue> {
170 if let Some(WriteCacheItem::Write(entry)) =
171 self.storage_write_cache.read().get(key)
172 {
173 return Some(*entry);
174 }
175 if let Some(entry) = self.storage_committed_cache.read().get(key) {
176 return Some(*entry);
177 }
178 if let Some(entry) = self.storage_read_cache.read().get(key) {
179 return Some(*entry);
180 }
181 None
182 }
183
184 #[cfg(test)]
185 pub fn cached_value_at_cache(&self, key: &[u8]) -> Option<U256> {
186 self.cached_entry_at(key).map(|e| e.value)
187 }
188
189 #[cfg(test)]
190 fn cached_entry_at_checkpoint(
191 &self, key: &[u8], state_checkpoint_id: usize,
192 ) -> Option<CheckpointEntry<StorageValue>> {
193 use CheckpointEntry::*;
194 if self.storage_write_checkpoint.is_none() {
195 return None;
196 }
197 if self
198 .storage_write_checkpoint
199 .as_ref()
200 .unwrap()
201 .read()
202 .get_state_cp_id()
203 < state_checkpoint_id
204 {
205 return None;
206 }
207 let res = self
208 .storage_write_checkpoint
209 .as_ref()
210 .unwrap()
211 .read()
212 .get(key)?;
213 Some(match res {
214 Unchanged => Unchanged,
215 Recorded(WriteCacheItem::Read) => Unchanged,
216 Recorded(WriteCacheItem::Write(v)) => Recorded(v),
217 })
218 }
219
220 #[cfg(test)]
221 pub fn cached_value_at_checkpoint(
222 &self, key: &[u8], state_checkpoint_id: usize,
223 ) -> Option<CheckpointEntry<U256>> {
224 self.cached_entry_at_checkpoint(key, state_checkpoint_id)
225 .map(|e: CheckpointEntry<StorageValue>| match e {
226 CheckpointEntry::Unchanged => CheckpointEntry::Unchanged,
227 CheckpointEntry::Recorded(sv) => {
228 CheckpointEntry::Recorded(sv.value)
229 }
230 })
231 }
232
233 pub fn storage_at(
237 &self, db: &StateDbGeneric, key: &[u8],
238 ) -> DbResult<U256> {
239 Ok(self.storage_entry_at(db, key)?.value)
240 }
241
242 pub fn origin_storage_at(&self, key: &[u8]) -> Option<U256> {
243 if let Some(value) = self.storage_committed_cache.read().get(key) {
244 return Some(value.value);
245 }
246 if self.fresh_storage() && !self.storage_overrided {
247 return Some(U256::zero());
248 }
249 if let Some(value) = self.storage_read_cache.read().get(key) {
250 return Some(value.value);
251 }
252 if self.storage_overrided {
253 return Some(U256::zero());
254 }
255 None
256 }
257
258 pub fn storage_entry_at(
262 &self, db: &StateDbGeneric, key: &[u8],
263 ) -> DbResult<StorageValue> {
264 self.mark_storage_warm(key);
265 Ok(if let Some(value) = self.cached_entry_at(key) {
266 value
267 } else if self.fresh_storage() {
268 StorageValue::default()
269 } else {
270 self.get_and_cache_storage(db, key)?
271 })
272 }
273
274 pub fn transient_storage_at(&self, key: &[u8]) -> U256 {
275 self.transient_storage_cache
276 .read()
277 .get(key)
278 .cloned()
279 .unwrap_or_default()
280 }
281
282 fn get_and_cache_storage(
283 &self, db: &StateDbGeneric, key: &[u8],
284 ) -> DbResult<StorageValue> {
285 let storage_key =
286 StorageKey::new_storage_key(&self.address.address, key.as_ref())
287 .with_space(self.address.space);
288 let StorageValue { mut owner, value } =
289 db.get::<StorageValue>(storage_key)?.unwrap_or_default();
290 if !value.is_zero() && owner.is_none() && self.should_have_owner(key) {
291 owner = Some(self.address.address)
292 }
293 let storage_value = StorageValue { owner, value };
294 self.storage_read_cache
295 .write()
296 .insert(key.to_vec(), storage_value.clone());
297 Ok(storage_value)
298 }
299
300 pub fn transient_set_storage(&mut self, key: Vec<u8>, value: U256) {
301 self.insert_transient_write_cache(key, value);
302 }
303
304 pub(super) fn should_have_owner(&self, _key: &[u8]) -> bool {
305 self.address.space == Space::Native
306 && self.address.address != SYSTEM_STORAGE_ADDRESS
307 }
308
309 pub fn change_storage_value(
310 &mut self, db: &StateDbGeneric, key: &[u8], value: U256,
311 ) -> DbResult<()> {
312 let mut entry = self.storage_entry_at(db, key)?;
313 if !entry.value.is_zero() {
314 entry.value = value;
315 self.insert_storage_write_cache(key.to_vec(), entry);
316 } else {
317 warn!("Change storage value outside transaction fails: current value is zero, tx {:?}, key {:?}", self.address, key);
318 }
319 Ok(())
320 }
321
322 pub fn is_warm_storage_entry(&self, key: &[u8]) -> bool {
323 self.storage_write_cache.read().get(key).is_some()
324 }
325
326 #[cfg(test)]
327 pub fn storage_layout_change(&self) -> Option<&StorageLayout> {
328 self.storage_layout_change.as_ref()
329 }
330
331 #[cfg(test)]
332 pub fn set_storage_layout(&mut self, layout: StorageLayout) {
333 self.storage_layout_change = Some(layout);
334 }
335}
336
337fn decode_storage_key(key: &Vec<u8>) -> Option<Vec<u8>> {
338 if let StorageKeyWithSpace {
339 key: StorageKey::StorageKey { storage_key, .. },
340 ..
341 } = StorageKeyWithSpace::from_key_bytes::<SkipInputCheck>(&key[..])
342 {
343 Some(storage_key.to_vec())
344 } else {
345 None
347 }
348}