1#[macro_use]
6extern crate cfx_util_macros;
7#[macro_use]
8extern crate log;
9
10pub mod global_params;
11#[cfg(feature = "testonly_code")]
12mod in_memory_storage;
13mod statedb_ext;
14use cfx_types::H256;
15use primitives::StorageValue;
16
17use cfx_db_errors::statedb as error;
18
19#[cfg(test)]
20mod tests;
21
22pub use self::{
23 error::{Error, Result},
24 impls::StateDb as StateDbGeneric,
25 statedb_ext::StateDbExt,
26};
27pub use cfx_storage::utils::access_mode;
28pub type StateDb = StateDbGeneric;
29
30mod impls {
33 type Key = Vec<u8>;
34 type Value = Option<Arc<[u8]>>;
35
36 type AccessedEntries = BTreeMap<Key, EntryValue>;
39
40 pub struct StateDb {
42 accessed_entries: RwLock<AccessedEntries>,
45
46 storage: Box<dyn StorageStateTrait>,
49 }
50
51 impl StateDb {
52 pub fn new(storage: Box<dyn StorageStateTrait>) -> Self {
53 StateDb {
54 accessed_entries: Default::default(),
55 storage,
56 }
57 }
58
59 #[cfg(feature = "testonly_code")]
60 pub fn new_for_unit_test() -> Self {
61 use self::in_memory_storage::InmemoryStorage;
62
63 Self::new(Box::new(InmemoryStorage::default()))
64 }
65
66 #[cfg(feature = "testonly_code")]
67 pub fn new_for_unit_test_with_epoch(epoch_id: &EpochId) -> Self {
68 use self::in_memory_storage::InmemoryStorage;
69
70 Self::new(Box::new(
71 InmemoryStorage::from_epoch_id(epoch_id).unwrap(),
72 ))
73 }
74
75 #[cfg(test)]
76 pub fn get_from_cache(&self, key: &Vec<u8>) -> Value {
77 self.accessed_entries
78 .read()
79 .get(key)
80 .and_then(|v| v.current_value.clone())
81 }
82
83 pub(crate) fn get_raw(
85 &self, key: StorageKeyWithSpace,
86 ) -> Result<Option<Arc<[u8]>>> {
87 let key_bytes = key.to_key_bytes();
88 let r;
89 let accessed_entries_read_guard = self.accessed_entries.read();
90 if let Some(v) = accessed_entries_read_guard.get(&key_bytes) {
91 r = v.current_value.clone();
92 } else {
93 drop(accessed_entries_read_guard);
94 let mut accessed_entries = self.accessed_entries.write();
95 let entry = accessed_entries.entry(key_bytes);
96 if let Occupied(o) = &entry {
97 r = o.get().current_value.clone();
98 } else {
99 r = self.storage.get(key)?.map(Into::into);
100 entry.or_insert(EntryValue::new(r.clone()));
101 };
102 };
103 trace!("get_raw key={:?}, value={:?}", key, r);
104 Ok(r)
105 }
106
107 #[cfg(feature = "testonly_code")]
108 pub fn get_raw_test(
109 &self, key: StorageKeyWithSpace,
110 ) -> Result<Option<Arc<[u8]>>> {
111 self.get_raw(key)
112 }
113
114 fn modify_single_value(
118 &mut self, key: StorageKeyWithSpace, value: Option<Box<[u8]>>,
119 ) -> Result<()> {
120 let key_bytes = key.to_key_bytes();
121 let mut entry =
122 self.accessed_entries.get_mut().entry(key_bytes.clone());
123 let value = value.map(Into::into);
124
125 match &mut entry {
126 Occupied(o) => {
127 Some(std::mem::replace(
129 &mut o.get_mut().current_value,
130 value,
131 ))
132 }
133
134 &mut Vacant(_) => {
136 let original_value = self.storage.get(key)?.map(Into::into);
137
138 entry.or_insert(EntryValue::new_modified(
139 original_value,
140 value,
141 ));
142
143 None
144 }
145 };
146
147 Ok(())
148 }
149
150 pub(crate) fn set_raw(
151 &mut self, key: StorageKeyWithSpace, value: Box<[u8]>,
152 debug_record: Option<&mut ComputeEpochDebugRecord>,
153 ) -> Result<()> {
154 if let Some(record) = debug_record {
155 record.state_ops.push(StateOp::StorageLevelOp {
156 op_name: "set".into(),
157 key: key.to_key_bytes(),
158 maybe_value: Some(value.clone().into()),
159 })
160 }
161
162 self.modify_single_value(key, Some(value))
163 }
164
165 pub fn delete(
166 &mut self, key: StorageKeyWithSpace,
167 debug_record: Option<&mut ComputeEpochDebugRecord>,
168 ) -> Result<()> {
169 if let Some(record) = debug_record {
170 record.state_ops.push(StateOp::StorageLevelOp {
171 op_name: "delete".into(),
172 key: key.to_key_bytes(),
173 maybe_value: None,
174 })
175 }
176
177 self.modify_single_value(key, None)
178 }
179
180 pub fn read_all(
181 &mut self, key_prefix: StorageKeyWithSpace,
182 debug_record: Option<&mut ComputeEpochDebugRecord>,
183 ) -> Result<Vec<MptKeyValue>> {
184 self.delete_all::<access_mode::Read>(key_prefix, debug_record)
185 }
186
187 pub fn read_all_with_callback(
188 &mut self, access_key_prefix: StorageKeyWithSpace,
189 callback: &mut dyn FnMut(MptKeyValue), only_account_key: bool,
190 ) -> Result<()> {
191 self.storage
192 .read_all_with_callback(
193 access_key_prefix,
194 callback,
195 only_account_key,
196 )
197 .map_err(|err| err.into())
198 }
199
200 pub fn delete_all<AM: access_mode::AccessMode>(
201 &mut self, key_prefix: StorageKeyWithSpace,
202 debug_record: Option<&mut ComputeEpochDebugRecord>,
203 ) -> Result<Vec<MptKeyValue>> {
204 let key_bytes = key_prefix.to_key_bytes();
205 if let Some(record) = debug_record {
206 record.state_ops.push(StateOp::StorageLevelOp {
207 op_name: if AM::READ_ONLY {
208 "iterate"
209 } else {
210 "delete_all"
211 }
212 .into(),
213 key: key_bytes.clone(),
214 maybe_value: None,
215 })
216 }
217 let accessed_entries = self.accessed_entries.get_mut();
218 let iter_range_upper_bound =
220 to_key_prefix_iter_upper_bound(&key_bytes);
221 let iter_range = match &iter_range_upper_bound {
222 None => accessed_entries
223 .range_mut::<[u8], _>((Included(&*key_bytes), Unbounded)),
224
225 Some(upper_bound) => accessed_entries.range_mut::<[u8], _>((
230 Included(&*key_bytes),
231 Excluded(&**upper_bound),
232 )),
233 };
234 let mut deleted_kvs = vec![];
235 for (k, v) in iter_range {
236 if v.current_value != None {
237 deleted_kvs.push((
238 k.clone(),
239 (&**v.current_value.as_ref().unwrap()).into(),
240 ));
241 if !AM::READ_ONLY {
242 v.current_value = None;
243 }
244 }
245 }
246 let deleted = self.storage.read_all(key_prefix)?;
248 if let Some(storage_deleted) = &deleted {
250 for (k, v) in storage_deleted {
251 let entry = accessed_entries.entry(k.clone());
252 let was_vacant = if let Occupied(_) = &entry {
253 false
256 } else {
257 true
258 };
259 if was_vacant {
260 deleted_kvs.push((k.clone(), v.clone()));
261 if !AM::READ_ONLY {
262 entry.or_insert(EntryValue::new_modified(
263 Some((&**v).into()),
264 None,
265 ));
266 }
267 }
268 }
269 }
270
271 Ok(deleted_kvs)
272 }
273
274 pub fn get_account_storage_entries(
275 &mut self, address: &AddressWithSpace,
276 debug_record: Option<&mut ComputeEpochDebugRecord>,
277 ) -> Result<BTreeMap<cfx_types::StorageKey, cfx_types::StorageValue>>
278 {
279 let mut storage = BTreeMap::new();
280
281 let storage_prefix =
282 StorageKey::new_storage_root_key(&address.address)
283 .with_space(address.space);
284
285 let kv_pairs = self.read_all(storage_prefix, debug_record)?;
286 for (key, value) in kv_pairs {
287 let storage_key_with_space =
288 StorageKeyWithSpace::from_key_bytes::<SkipInputCheck>(&key);
289 if let StorageKey::StorageKey {
290 address_bytes: _,
291 storage_key,
292 } = storage_key_with_space.key
293 {
294 let h256_storage_key = H256::from_slice(storage_key);
295 let storage_value_with_owner: StorageValue =
296 rlp::decode(&value)?;
297 storage.insert(
298 h256_storage_key,
299 storage_value_with_owner.value,
300 );
301 } else {
302 trace!("Not an storage key: {:?}", storage_key_with_space);
303 continue;
304 }
305 }
306
307 Ok(storage)
308 }
309
310 fn load_storage_layout(
318 storage_layouts_to_rewrite: &mut HashMap<
319 (Vec<u8>, Space),
320 StorageLayout,
321 >,
322 accept_account_deletion: bool, address: &[u8], space: Space,
323 storage: &dyn StorageStateTrait,
324 accessed_entries: &AccessedEntries,
325 ) -> Result<()> {
326 if storage_layouts_to_rewrite
327 .contains_key(&(address.to_vec(), space))
328 {
329 return Ok(());
330 }
331 let storage_layout_key =
332 StorageKey::StorageRootKey(address).with_space(space);
333 let current_storage_layout = match accessed_entries
334 .get(&storage_layout_key.to_key_bytes())
335 {
336 Some(entry) => match &entry.current_value {
337 None => {
340 if accept_account_deletion {
341 return Ok(());
342 } else {
343 bail!(Error::IncompleteDatabase(
347 Address::from_slice(address)
348 ));
349 }
350 }
351
352 Some(value_ref) => StorageLayout::from_bytes(&*value_ref)?,
353 },
354 None => match storage.get(storage_layout_key)? {
355 None => bail!(Error::IncompleteDatabase(
358 Address::from_slice(address)
359 )),
360 Some(raw) => StorageLayout::from_bytes(raw.as_ref())?,
361 },
362 };
363 storage_layouts_to_rewrite
364 .insert((address.into(), space), current_storage_layout);
365
366 Ok(())
367 }
368
369 pub fn set_storage_layout(
370 &mut self, address: &AddressWithSpace,
371 storage_layout: StorageLayout,
372 debug_record: Option<&mut ComputeEpochDebugRecord>,
373 ) -> Result<()> {
374 self.set_raw(
375 StorageKey::new_storage_root_key(&address.address)
376 .with_space(address.space),
377 storage_layout.to_bytes().into_boxed_slice(),
378 debug_record,
379 )
380 }
381
382 fn commit_storage_layout(
385 &mut self, address: &[u8], space: Space, layout: &StorageLayout,
386 debug_record: Option<&mut ComputeEpochDebugRecord>,
387 ) -> Result<()> {
388 let key = StorageKey::StorageRootKey(address).with_space(space);
389 let value = layout.to_bytes().into_boxed_slice();
390 if let Some(record) = debug_record {
391 record.state_ops.push(StateOp::StorageLevelOp {
392 op_name: "commit_storage_layout".into(),
393 key: key.to_key_bytes(),
394 maybe_value: Some(value.clone().into()),
395 })
396 };
397 Ok(self.storage.set(key, value)?)
398 }
399
400 fn apply_changes_to_storage(
401 &mut self, mut debug_record: Option<&mut ComputeEpochDebugRecord>,
402 ) -> Result<()> {
403 let mut storage_layouts_to_rewrite = Default::default();
404 let accessed_entries = &*self.accessed_entries.get_mut();
405 for (k, v) in accessed_entries {
407 if !v.is_modified() {
408 continue;
409 }
410
411 let storage_key =
412 StorageKeyWithSpace::from_key_bytes::<SkipInputCheck>(k);
413 match &v.current_value {
414 Some(v) => {
415 self.storage.set(storage_key, (&**v).into())?;
416 }
417 None => {
418 self.storage.delete(storage_key)?;
419 }
420 }
421
422 match &storage_key.key {
423 StorageKey::StorageKey { address_bytes, .. } => {
424 Self::load_storage_layout(
425 &mut storage_layouts_to_rewrite,
426 v.current_value.is_none(),
428 address_bytes,
429 storage_key.space,
430 self.storage.as_ref(),
431 &accessed_entries,
432 )?;
433 }
434 StorageKey::AccountKey(address_bytes)
435 if (address_bytes.is_builtin_address()
436 || address_bytes.is_contract_address()
437 || storage_key.space == Space::Ethereum)
438 && v.original_value.is_none() =>
439 {
440 let result = Self::load_storage_layout(
441 &mut storage_layouts_to_rewrite,
442 false,
443 address_bytes,
444 storage_key.space,
445 self.storage.as_ref(),
446 &accessed_entries,
447 );
448 if result.is_err() {
449 debug!(
450 "Contract address {:?} (space {:?}) is created without storage_layout. \
451 It's probably created by a balance transfer.",
452 Address::from_slice(address_bytes), storage_key.space
453 );
454 }
455 }
456 StorageKey::CodeKey { address_bytes, .. }
457 if v.original_value.is_none() =>
458 {
459 Self::load_storage_layout(
460 &mut storage_layouts_to_rewrite,
461 false,
462 address_bytes,
463 storage_key.space,
464 self.storage.as_ref(),
465 &accessed_entries,
466 )?;
467 }
468 _ => {}
469 }
470 }
471 for ((k, space), v) in &storage_layouts_to_rewrite {
474 self.commit_storage_layout(
475 k,
476 *space,
477 v,
478 debug_record.as_deref_mut(),
479 )?;
480 }
481 self.accessed_entries = Default::default();
483 Ok(())
484 }
485
486 pub fn compute_state_root(
491 &mut self, debug_record: Option<&mut ComputeEpochDebugRecord>,
492 ) -> Result<StateRootWithAuxInfo> {
493 self.apply_changes_to_storage(debug_record)?;
494 Ok(self.storage.compute_state_root()?)
495 }
496
497 pub fn commit(
498 &mut self, epoch_id: EpochId,
499 mut debug_record: Option<&mut ComputeEpochDebugRecord>,
500 ) -> Result<StateRootWithAuxInfo> {
501 self.apply_changes_to_storage(debug_record.as_deref_mut())?;
502
503 let result = match self.storage.get_state_root() {
504 Ok(r) => r,
505 Err(_) => self.compute_state_root(debug_record)?,
506 };
507
508 self.storage.commit(epoch_id)?;
509
510 Ok(result)
511 }
512 }
513
514 struct EntryValue {
515 original_value: Value,
516 current_value: Value,
517 }
518
519 impl EntryValue {
520 fn new(value: Value) -> Self {
521 let value_clone = value.clone();
522 Self {
523 original_value: value,
524 current_value: value_clone,
525 }
526 }
527
528 fn new_modified(original_value: Value, current_value: Value) -> Self {
529 Self {
530 original_value,
531 current_value,
532 }
533 }
534
535 fn is_modified(&self) -> bool {
536 self.original_value.ne(&self.current_value)
537 }
538 }
539
540 use super::*;
541 use cfx_internal_common::{
542 debug::{ComputeEpochDebugRecord, StateOp},
543 StateRootWithAuxInfo,
544 };
545 use cfx_storage::{
546 utils::{access_mode, to_key_prefix_iter_upper_bound},
547 MptKeyValue, StorageStateTrait,
548 };
549 use cfx_types::{
550 address_util::AddressUtil, Address, AddressWithSpace, Space,
551 };
552 use hashbrown::HashMap;
553 use parking_lot::RwLock;
554 use primitives::{
555 EpochId, SkipInputCheck, StorageKey, StorageKeyWithSpace, StorageLayout,
556 };
557 use std::{
558 collections::{
559 btree_map::Entry::{Occupied, Vacant},
560 BTreeMap,
561 },
562 ops::Bound::{Excluded, Included, Unbounded},
563 sync::Arc,
564 };
565}