cfx_executor/state/overlay_account/
account_entry.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
5use std::ops::{Deref, DerefMut};
6
7use super::OverlayAccount;
8
9#[derive(Debug)]
10#[cfg_attr(test, derive(Clone))]
11pub struct AccountEntryWithWarm {
12    pub warm: bool,
13    pub entry: AccountEntry,
14}
15
16impl Deref for AccountEntryWithWarm {
17    type Target = AccountEntry;
18
19    fn deref(&self) -> &Self::Target { &self.entry }
20}
21
22impl DerefMut for AccountEntryWithWarm {
23    fn deref_mut(&mut self) -> &mut Self::Target { &mut self.entry }
24}
25
26/// Entry object in cache and checkpoint layers, adding additional markers
27/// like dirty bits to the `OverlayAccount` structure.
28#[derive(Debug)]
29#[cfg_attr(test, derive(Clone))]
30pub enum AccountEntry {
31    /// Represents an account that is confirmed to be absent from the database.
32    DbAbsent,
33    /// An in-memory cached account paired with a dirty bit to indicate
34    /// modifications.
35    Cached(OverlayAccount, bool),
36}
37
38use cfx_parameters::genesis::GENESIS_ACCOUNT_ADDRESS;
39use cfx_types::AddressWithSpace;
40use primitives::Account;
41use AccountEntry::*;
42
43impl AccountEntry {
44    pub fn new_dirty(account: OverlayAccount) -> AccountEntry {
45        Cached(account, true)
46    }
47
48    /// Contruct `AccountEntry` from account loaded from statedb.
49    pub fn new_loaded(account: Option<Account>) -> AccountEntry {
50        match account {
51            Some(acc) => Cached(
52                OverlayAccount::from_loaded(&acc.address().clone(), acc),
53                false,
54            ),
55            None => DbAbsent,
56        }
57    }
58
59    #[allow(unused)]
60    pub fn is_dirty(&self) -> bool { matches!(self, Cached(_, true)) }
61
62    pub fn is_db_absent(&self) -> bool { matches!(self, DbAbsent) }
63
64    pub fn account(&self) -> Option<&OverlayAccount> {
65        match self {
66            DbAbsent => None,
67            Cached(acc, _) => Some(acc),
68        }
69    }
70
71    pub fn account_mut(&mut self) -> Option<&mut OverlayAccount> {
72        match self {
73            DbAbsent => None,
74            Cached(acc, _) => Some(acc),
75        }
76    }
77
78    pub fn dirty_account_mut(&mut self) -> Option<&mut OverlayAccount> {
79        match self {
80            Cached(acc, true) => Some(acc),
81            _ => None,
82        }
83    }
84
85    pub fn into_to_commit_account(self) -> Option<OverlayAccount> {
86        // Due to an existing bug, the genesis account is very special. It is
87        // always considered to be committed even if it is not dirty.
88        const SPECIAL_ADDRESS: AddressWithSpace = AddressWithSpace {
89            address: GENESIS_ACCOUNT_ADDRESS,
90            space: cfx_types::Space::Native,
91        };
92
93        match self {
94            Cached(acc, true) => Some(acc),
95            Cached(acc, _) if acc.address == SPECIAL_ADDRESS => Some(acc),
96            _ => None,
97        }
98    }
99
100    pub fn clone_cache_entry_for_checkpoint(
101        &self, checkpoint_id: usize,
102    ) -> AccountEntry {
103        match self {
104            DbAbsent => DbAbsent,
105            Cached(acc, dirty_bit) => Cached(
106                acc.clone_account_for_checkpoint(checkpoint_id),
107                *dirty_bit,
108            ),
109        }
110    }
111
112    pub fn clone_from_committed_cache(&self) -> AccountEntry {
113        match self {
114            DbAbsent => DbAbsent,
115            Cached(acc, dirty_bit) => {
116                Cached(acc.clone_from_committed_cache(), *dirty_bit)
117            }
118        }
119    }
120
121    pub fn clone_account(&self) -> AccountEntry {
122        match self {
123            DbAbsent => DbAbsent,
124            Cached(acc, dirty_bit) => Cached(acc.clone_account(), *dirty_bit),
125        }
126    }
127
128    pub fn with_warm(self, warm: bool) -> AccountEntryWithWarm {
129        AccountEntryWithWarm { warm, entry: self }
130    }
131}