cfx_executor/state/state_object/
state_override.rs

1use super::State;
2use crate::state::overlay_account::AccountEntry;
3use cfx_rpc_eth_types::StateOverride;
4use cfx_statedb::{Result as DbResult, StateDbExt, StateDbGeneric as StateDb};
5use cfx_types::{AddressWithSpace, Space};
6
7/// Apply the state override to the state object, only used for rpc call eg
8/// eth_call, eth_estimateGas etc.
9impl State {
10    pub fn new_with_override(
11        db: StateDb, state_override: &StateOverride, space: Space,
12    ) -> DbResult<Self> {
13        let mut state = Self::new(db)?;
14        state.apply_override(state_override, space)?;
15        Ok(state)
16    }
17
18    fn apply_override(
19        &mut self, state_override: &StateOverride, space: Space,
20    ) -> DbResult<()> {
21        assert!(self.checkpoints.read().is_empty());
22
23        let mut cache = self.cache.write();
24        for (address, account) in state_override.iter() {
25            let addr_with_space = AddressWithSpace {
26                address: address.to_owned(),
27                space,
28            };
29
30            let loaded_account = self.db.get_account(&addr_with_space)?;
31            // The override phase's warm bit is not important because it will
32            // soon be written from the cache to the committed cache, which does
33            // not include the warm bit.
34            let account_entry = AccountEntry::from_loaded_with_override(
35                &addr_with_space,
36                loaded_account,
37                account,
38            )
39            .with_warm(false);
40
41            cache.insert(addr_with_space, account_entry);
42        }
43        Ok(())
44    }
45}